138 lines
5.2 KiB
Python
138 lines
5.2 KiB
Python
"""
|
||
问题改写
|
||
"""
|
||
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} # 兜底 |