一、问题
我们希望实现人们通过自然的口语对话来使用大模型应用。然而,在口语表达需求和意图时,人们往往会遇到一些问题。例如,表达过于简略或含糊,容易引发语义歧义,导致大模型产生误解;
用户的问题可能包含许多隐含要素,但表达的信息却不足,智能通过多轮对话逐步补全;
理想情况:通过大模型多次主动与用户沟通,不断收集信息,完善对用户真实意图的理解,补全执行用户需求所需的各项参数

理想情况
二、示例代码
import json
from langchain_core.output_parsers import StrOutputParser, JsonOutputParser
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables import RunnableWithMessageHistory
from Common import get_dashscopeModel
llm = get_dashscopeModel()
user_input = str(input("请输入你的需求:"))
# 根据用户要求,进行意图识别,获取对应的模板
# 示例业务模板
templates = {
"订机票":[
{
"paramsKey":"start",
"paramsName":"起点"
},
{
"paramsKey":"end",
"paramsName":"终点"
},
{
"paramsKey":"date",
"paramsName":"日期"
},
{
"paramsKey":"people",
"paramsName":"人数"
},
{
"paramsKey":"level",
"paramsName":"座位等级"
},
{
"paramsKey":"preference",
"paramsName":"座位偏好"
}
],
"订酒店":["城市", "入住日期", "离店日期", "人数", "房型"]
}
# 意图识别提示词模板
input_prompt = PromptTemplate(
input_variables=["user_input","template"],
template="根据用户输入'{user_input}',选择最合适的业务模板。可用业务模板有:{templates}。请返回模板名称。"
)
intent_chain = input_prompt | llm | StrOutputParser()
# 意图识别
intent = intent_chain.invoke({"user_input":user_input, "templates":str(list(templates.keys()))})
print(f"意图识别结果:{intent}")
# 获取对应的模板
select_template = templates.get( intent)
print(f"选择的模板为:{select_template}")
# 根据用户意图选择的模板,进行参数识别
# 补充信息提示模板{",".join(select_template)}
info_prompt = f"""
请根据用户原始问题和模板,判断原始问题是否完善。
如果问题缺乏需要的信息,请生成一个友好的请求,明确指出需要补充的信息,严格按照模板指出的参数,不要添加其他信息。
若问题完善后,返回包含所有信息的完整问题。
### 原始问题
{user_input}
### 模板
{select_template}
### 输出示例
{{
"isComplete": true,
"content":"完整问题",
"data":{{
"intent":"订机票",
"params":收集到的select_template内的参数paramsKey作为键值,值为用户输入的参数值
}}
}}
{{
"isComplete": false,
"content":"友好的引导用户补充需要的信息",
"data":{{}}
}}
"""
# 历史记录
chat_history = ChatMessageHistory()
# 聊天模板
prompt = ChatPromptTemplate.from_messages(
[
("system","你是一个信息补充助手,任务是分析用户问题是否完善"),
("human", "{history}"), # 历史消息
("human", "{input}")
]
)
# 补充消息链
info_chain = prompt | llm | StrOutputParser()
#自动处理历史记录,将记录注入输入并在每次调用后更新它
with_message_history = RunnableWithMessageHistory(
info_chain,
lambda session_id:chat_history,
input_messages_key="input",
history_messages_key="history"
)
# 判断问题是否完整,如果不完整则返回引导信息
info_request = with_message_history.invoke({"input":info_prompt},config={"configurable":{"session_id":"unused"}})
parser = JsonOutputParser()
json_data = parser.parse(info_request)
print(json_data)
# 循环判断是否完整,并提交用户补充信息
while json_data.get("isComplete", False) is False:
try:
# 显示引导信息并等待用户输入,用\033[1;33m和\033[0m设置和重置文本颜色及样式(黄色加粗)
user_answer = input(f"\033[1;33m{json_data['content']}\033[0m\n请补充:")
info_request = with_message_history.invoke(
input={"input":user_answer},
config={"configurable":{"session_id":"unused"}}
)
# 解析结果
json_data = parser.parse(info_request)
except json.JSONDecodeError as e:
print("\033[1;31m[错误] AI返回了无效的JSON格式,请重试\033[0m")
continue
except KeyError as e:
print("\033[1;31m[错误] 响应格式异常,正在终止流程\033[0m")
break
# 输出最终结果
print(f"\033[1;32m[最终查询] {info_request}\033[0m")

输出结果