""" 问题改写 """ from langchain_core.output_parsers import JsonOutputParser from langchain_core.prompts import PromptTemplate from app.chat_qa_query.query_qa_state import QueryQAState from app.llm import llm from app.core.log import logger problem_rewriting_prompt = """ 你是一名智能客服意图分类助手。你的任务是根据用户的历史会话和当前问题,提取用户的核心诉求,并输出标准化的意图标签。 ## 核心原则(必须严格遵守) ### 1. 双维度提取原则 每个用户问题通常包含两个维度的意图,必须分别识别: - **课程/服务主题维度**:用户想咨询的具体课程类型或业务主题(如3D建模、2D原画、UE引擎开发等) - **诉求/动作维度**:用户想了解的方面(如课程咨询、就业咨询、校区分布等) 这两个维度相互独立,必须同时提取,不得遗漏任何一个。 ### 2. 主题维度提取规则 - 如果用户明确提到了具体课程名称或类型(如"3D建模"、"2D原画"、"UE引擎开发"),必须作为独立意图标签输出 - 如果当前问题使用代词(如"这个"、"它"),结合历史会话进行指代消解,还原具体课程名称 - 如果历史会话中也没有明确课程类型,则不输出主题维度标签 ### 3. 诉求维度提取规则 - 从当前问题中提取用户明确表达的动作诉求(费用、就业、退费、住宿等) - 将动作诉求映射到标准诉求类型标签 ### 4. 信息补全与语义保持 - 如果当前问题缺少主语,从历史会话补全 - 不得改变用户原始意图,不得引入历史会话中不存在的新信息 - 不得遗漏当前问题中的任何关键诉求 ## 输出格式 - 仅输出JSON,不要任何解释性文字 - 多诉求时用数组形式输出,每个意图标签独立 - 标签从以下列表中选择,不得自创: **课程/服务主题标签**:公司介绍、3D建模、3D场景建模、3D角色建模、2D原画、二次元风格、写实风格、动作/分镜、游戏动作/分镜、开发、UE引擎开发、3D大师课、GGAC绘殓课程、造型力、大学生扶持计划、兴趣/提升班、学习模式、线下面授教学、线上直播教学、寒暑假教学、提供服务、优势/竞争力、校区分布 **诉求/动作标签**:课程咨询、退费咨询、住宿咨询、学不会怎么办、就业咨询、学历咨询 ## 分类示例 ### 示例1(主题+诉求双维度) 历史会话:(空) 当前问题:3D建模培训的课程内容有哪些? 分析:主题="3D建模",诉求="课程内容"→课程咨询 分类结果: {{ "intents": ["3D建模", "课程咨询"] }} ### 示例2(主题+诉求双维度,信息补全) 历史会话: - 用户:我想了解游戏特效培训 - 助手:好的,请问您想了解哪方面? 当前问题:培训的费用 分析:主题从历史会话补全="游戏特效培训",诉求="费用"→课程咨询 分类结果: {{ "intents": ["课程咨询"] }} ### 示例3(主题+诉求双维度,指代消解) 历史会话: - 用户:你们有Python课程吗? - 助手:有的,我们有Python基础班和进阶班。 当前问题:这个课程的时长是多久? 分析:主题="Python课程",诉求="课程时长"→课程咨询 分类结果: {{ "intents": ["课程咨询"] }} ### 示例4(多诉求提取) 历史会话: - 用户:我想报名数据分析培训 当前问题:流程、费用和就业支持 分析:主题="数据分析培训",诉求="流程/费用"→课程咨询,"就业支持"→就业咨询 分类结果: {{ "intents": ["课程咨询", "就业咨询"] }} ### 示例5(主题+诉求双维度) 历史会话:(空) 当前问题:老师3D大师课课程多少钱啊,老师我想报班 分析:主题="3D大师课",诉求="多少钱/报班"→课程咨询 分类结果: {{ "intents": ["3D大师课", "课程咨询"] }} ### 示例6(关键示例:主题必须独立提取) 历史会话: - 用户:老师 我想报班 - 用户:老师这个课程多少钱啊 当前问题:老师我想咨询3D建模费用问题 分析:主题="3D建模"(当前问题明确提及),诉求="费用问题"→课程咨询 分类结果: {{ "intents": ["3D建模", "课程咨询"] }} --- ## 现在请处理以下输入 当前问题:{query} 历史聊天:{history_text} 请直接输出JSON: """ async def rewrite_query(state:QueryQAState): """ 问题改写 :param query: 用户问题 :param history_text: 历史会话 :return: 改写后的问题 """ history_text = state.get("history", "") query = state.get("original_query", "") prompt = PromptTemplate(template=problem_rewriting_prompt, input_variables=["history_text", "query"]) output = JsonOutputParser() chain = prompt | llm | output try: result = await chain.ainvoke({"history_text": history_text, "query": query}) rewritten_query = result.get("intents", "") logger.info(f"原问题:{query},历史会话:{history_text},改写后问题:{rewritten_query}") return {"rewritten_query": rewritten_query} except Exception as e: logger.error(f"QA质量检查prompt模板错误:{e}") return {"rewritten_query": query} # 兜底