sales-assistant-py-new/app/chat_qa_query/query_nodes/node_rewrite.py

121 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
问题改写
"""
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} # 兜底