121 lines
3.9 KiB
Python
121 lines
3.9 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. **核心诉求提取**:
|
||
- 从当前问题中提取用户明确表达的诉求(可能有一个或多个,去重)
|
||
- 如果当前问题包含代词(如"这个"、"它"、"那"等),必须结合历史会话进行指代消解,用具体名词替换代词
|
||
|
||
2. **信息补全**:
|
||
- 如果当前问题缺少主语或关键上下文(如只问"费用多少"),必须从历史会话中提取相关主题补全
|
||
- 确保意图标签不依赖历史会话也能被独立理解
|
||
|
||
3. **语义保持**:
|
||
- 不得改变用户的原始意图
|
||
- 不得引入历史会话中不存在的新信息
|
||
- 不得遗漏当前问题中的任何关键诉求
|
||
|
||
4. **输出格式**:
|
||
- 仅输出JSON,不要任何解释性文字
|
||
- 输出为结构化的意图标签数组,**不要改写成完整问句**
|
||
- 每个意图标签应简洁、标准化,适合用于分类路由
|
||
- 多诉求时拆分为多个意图标签,用数组形式输出
|
||
|
||
## 意图标签规范
|
||
|
||
- 每个标签格式为:"{{诉求类型}}"
|
||
- 常见诉求类型:费用咨询、课程内容、报名流程、就业支持、开班时间、校区地址、优惠活动、退款政策、住宿咨询、其他
|
||
- 标签应简洁、无歧义,便于系统直接匹配路由
|
||
- 从当前问题中提取用户明确表达的诉求,可以提取多个意图标签
|
||
|
||
## 分类示例
|
||
|
||
### 示例1(信息补全)
|
||
历史会话:
|
||
- 用户:我想了解游戏特效培训
|
||
- 助手:好的,请问您想了解哪方面?
|
||
当前问题:培训的费用
|
||
分类结果:
|
||
{{
|
||
"intents": "费用咨询"
|
||
}}
|
||
|
||
### 示例2(指代消解)
|
||
历史会话:
|
||
- 用户:你们有Python课程吗?
|
||
- 助手:有的,我们有Python基础班和进阶班。
|
||
当前问题:这个课程的时长是多久?
|
||
分类结果:
|
||
{{
|
||
"intents": ["课程内容", "报名流程"]
|
||
}}
|
||
|
||
### 示例3(多诉求提取)
|
||
历史会话:
|
||
- 用户:我想报名数据分析培训
|
||
当前问题:流程、费用和就业支持
|
||
分类结果:
|
||
{{
|
||
"intents": ["报名流程"]
|
||
}}
|
||
|
||
### 示例4(无需改写)
|
||
历史会话:(空)
|
||
当前问题:Java培训的课程内容有哪些?
|
||
分类结果:
|
||
{{
|
||
"intents": ["课程内容"]
|
||
}}
|
||
|
||
### 示例5(用户提供的案例)
|
||
历史会话:(空)
|
||
当前问题:老师这个课程多少钱啊,老师我想报班
|
||
分类结果:
|
||
{{
|
||
"intents": ["报名流程"]
|
||
}}
|
||
|
||
---
|
||
|
||
## 现在请处理以下输入
|
||
|
||
|
||
当前问题:{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", "")
|
||
if rewritten_query:
|
||
rewritten_query = rewritten_query[0]
|
||
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} # 兜底 |