基于LLM+场景识别+词槽实体抽取实现多轮问答

news/2025/3/5 2:01:34/

前言

随着人工智能技术的不断进步,大语言模型(LLM)已成为技术前沿的热点。它们不仅能够理解和生成文本,还能在多种应用场景中实现复杂的交互。本文将深入探讨一段结合了大语言模型能力、意图识别和词槽实体抽取的Python代码,这段代码展示了如何实现智能的多轮问答能力,为用户提供更加丰富和个性化的交互体验。

正文

完整代码

这段代码的核心在于集成了最新的大语言模型(LLM)能力,结合了意图识别和词槽实体抽取的技术,以实现智能的多轮问答。

import json
import re
import requests
from datetime import datetimeurl = 'https://api.openai.com/v1/chat/completions'# 替换为您自己的chatGPT API密钥
api_key = 'sk-xxxxxx'# 调试日志
debug = Falsedef check_values_not_empty(json_data):"""检查是否所有元素value都不为空"""# 遍历JSON数据中的每个元素for item in json_data:# 检查value字段是否为空字符串if item.get('value') == '':return False  # 如果发现空字符串,返回Falsereturn True  # 如果所有value字段都非空,返回Truedef format_title_value_for_logging(json_data):"""抽取参数名称和value值"""log_strings = []for item in json_data:title = item.get('title', 'Unknown Title')  # 获取title,如果不存在则使用'Unknown Title'value = item.get('value', 'N/A')  # 获取value,如果不存在则使用'N/A'log_string = f"Title: {title}, Value: {value}"log_strings.append(log_string)return '\n'.join(log_strings)def extract_json_from_string(input_string):"""JSON抽取函数返回包含JSON对象的列表"""try:# 正则表达式假设JSON对象由花括号括起来matches = re.findall(r'\{.*?\}', input_string, re.DOTALL)# 验证找到的每个匹配项是否为有效的JSONvalid_jsons = []for match in matches:try:json_obj = json.loads(match)valid_jsons.append(json_obj)except json.JSONDecodeError:continue  # 如果不是有效的JSON,跳过该匹配项return valid_jsonsexcept Exception as e:print(f"Error occurred: {e}")return []def send_message(message, user_input):"""请求LLM函数"""print('--------------------------------------------------------------------')if debug:print('用户输入:', message)else:print('用户输入:', user_input)print('----------------------------------')headers = {"Authorization": f"Bearer {api_key}","Content-Type": "application/json",}data = {"model": "gpt-3.5-turbo","messages": [{"role": "system", "content": "You are a helpful assistant."},{"role": "user", "content": f"{message}"}]}response = requests.post(url, headers=headers, json=data, verify=False)if response.status_code == 200:answer = response.json()["choices"][0]["message"]['content']print('LLM输出:', answer)print('--------------------------------------------------------------------')return answerelse:print(f"Error: {response.status_code}")return None# 问天气
# 参数:
# 1. 时间time(口语:今天明天、日期:10号、范围:未来一周)
# 2. 地点location(国家省市区)
# todo "transform": "时间格式转换工具?是自己做一个还是用大模型。建议自己开发一个",
dict_weather = [{"title": "时间","desc": "口语表述:昨天、今天、明天;具体日期:10号、1月1号、2月3日;范围:未来一周、最近十四天","transform": "时间统一转换格式,如果是时间点:yyyy-MM-dd;如果是时间段:yyyy-MM-dd#yyyy-MM-dd","util": "","value": "","required": True},{"title": "地点","desc": "口语表述:建邺区、南京、河北省、江苏南通、上海虹桥、北京朝阳区","transform": "地点统一转换格式为省市区(如果有区)或省市,如南京市建邺区、南京市,如果提取不到市只有省份则不填写value","util": "","value": "","required": True}
]prompt_weather_info_update = """
JSON每个元素代表一个参数信息,我先给你提供一些基本介绍:
'''
title字段是参数名称,如果需要让用户填写该参数时你应该告诉用户你需要的参数名称
desc字段是参数描述,可以做为title字段的补充,更好的引导用户补充参数
transform字段是填写value字段值的格式要求说明
required字段为true表示该元素的value是必填参数,如果value为空则必须让用户补充该参数信息,如果required字段为false表示该参数不是必须补充的字段
'''需求:
#01 根据用户输入信息提取有用的信息更新到JSON中的value字段并返回更新后的JSON
#02 仅更新value字段,其他字段都原样返回
#03 如果没有可更新的value则原样返回
#04 当前时间为{}参考示例:
'''
JSON: [{{"title": "时间","desc": "口语表述:昨天、今天、明天;具体日期:10号、1月1号、2月3日;范围:未来一周、最近十四天","transform": "时间统一转换格式,如果是时间点:yyyy-MM-dd;如果是时间段:yyyy-MM-dd#yyyy-MM-dd","util": "","value": "","required": true}},{{"title": "地点","desc": "口语表述:建邺区、南京、河北省、江苏南通、上海虹桥、北京朝阳区","transform": "地点统一转换格式为省市区(如果有区)或省市,如南京市建邺区、南京市,如果提取不到市只有省份则不填写value","util": "","value": "","required": true}}
]
问:今天南京天气怎么样?
答:[{{"title": "时间","desc": "口语表述:昨天、今天、明天;具体日期:10号、1月1号、2月3日;范围:未来一周、最近十四天","transform": "时间统一转换格式,如果是时间点:yyyy-MM-dd;如果是时间段:yyyy-MM-dd#yyyy-MM-dd","util": "","value": "{}","required": true}},{{"title": "地点","desc": "口语表述:建邺区、南京、河北省、江苏南通、上海虹桥、北京朝阳区","transform": "地点统一转换格式为省市区(如果有区)或省市,如南京市建邺区、南京市,如果提取不到市只有省份则不填写value","util": "","value": "南京","required": true}}
]
'''JSON:{}
问:{}
答:
"""prompt_weather_query_user = """
JSON每个元素代表一个参数信息,我先给你提供一些基本介绍:
'''
title字段是参数名称,如果需要让用户填写该参数时你应该告诉用户你需要的参数名称
desc字段是参数描述,可以做为title字段的补充,更好的引导用户补充参数
required字段为true表示该元素的value是必填参数,如果value为空则必须让用户补充该参数信息,如果required字段为false表示该参数不是必须补充的字段
'''需求:
#01 如果有多个未填写value的参数则可以一起向用户提问
#02 value已经填写的参数不用再次提问参考示例:
'''
问:[{{"title": "时间","desc": "口语表述:昨天、今天、明天;具体日期:10号、1月1号、2月3日;范围:未来一周、最近十四天","transform": "时间统一转换格式,如果是时间点:yyyy-MM-dd;如果是时间段:yyyy-MM-dd#yyyy-MM-dd","util": "","value": "2022-01-01","required": true}},{{"title": "地点","desc": "口语表述:建邺区、南京、河北省、江苏南通、上海虹桥、北京朝阳区","transform": "地点统一转换格式为省市区(如果有区)或省市,如南京市建邺区、南京市,如果提取不到市只有省份则不填写value","util": "","value": "","required": true}}
]
答:请问你想查询天气的地点是什么?
'''问:{}
答:
"""# 公积金咨询
# 参数:
# 1. 事件(买房、租房、退休)
# 2. 购买房屋类型(买房事件时需要 经济适用房、新房、二手房)
dict_consult = {"event": "","purchase_type": ""
}prompt_global_purpose = """
有下面多种场景,需要你根据用户输入进行判断
1. 问天气
2. 公积金咨询
3. 其他场景参考示例:
'''
问:今天天气如何
答:问天气
'''问:{}
答:
"""global_purpose = ''def multi_question(user_input):global global_purposeglobal dict_weathercurrent_purpose = send_message(prompt_global_purpose.format(user_input), user_input)if current_purpose != '其他场景':global_purpose = current_purposeif global_purpose == '问天气':# 先检查本次用户输入是否有信息补充,保存补充后的结果   编写程序进行字符串value值diff对比,判断是否有更新current_time = datetime.now().strftime("%Y-%m-%d")new_info_json_raw = send_message(prompt_weather_info_update.format(current_time, current_time, json.dumps(dict_weather, ensure_ascii=False), user_input), user_input)dict_weather = extract_json_from_string(new_info_json_raw)# 判断参数是否已经全部补全if check_values_not_empty(dict_weather):print('问天气 ------ 参数已完整,详细参数如下')print(format_title_value_for_logging(dict_weather))print('正在请求天气查询API,请稍后……')else:str = json.dumps(dict_weather, ensure_ascii=False)send_message(prompt_weather_query_user.format(str), user_input)elif global_purpose == '公积金咨询':passelse:passpassdef user_input():while True:question = input("请输入您的问题:")multi_question(question)# test
# multi_question("明天天气怎么样呢")
# multi_question("苏州天气怎么样呢")
# multi_question("苏州明天天气怎么样呢")user_input()
代码解析

整合大语言模型(LLM):代码通过与一个语言模型API的交互,利用了大语言模型的强大文本生成和理解能力。这使得脚本能够处理复杂的用户查询,并生成合理的响应。

意图识别:通过分析用户的输入,脚本可以识别用户的意图(例如查询天气或获取公积金咨询),这是通过向LLM发送特定的提示(prompt)实现的。

词槽实体抽取:代码能够从用户输入中提取关键信息(如时间和地点),并将这些信息填充到预定义的JSON结构中。这是通过正则表达式和JSON操作实现的。

多轮交互:脚本支持多轮交互,能够根据用户输入的不同,动态地提问和响应,为用户提供连贯且自然的对话体验。

代码的实用性

这个脚本不仅展示了如何在Python中处理复杂的数据结构和执行HTTP请求,还展示了大语言模型在实际应用中的巨大潜力。它为开发者提供了一个实用的框架,用于构建可以理解和响应人类语言的智能应用程序。LLM+场景识别+词槽实体抽取,实现人机交互多轮会话,遥遥领先~

结尾

我们可以看到大语言模型在理解和生成自然语言方面的巨大潜力。结合意图识别和词槽实体抽取,它能够实现复杂且自然的多轮对话。这种技术的应用范围非常广泛,从简单的信息查询到复杂的交互式任务都能得到有效的支持。

希望这篇文章能够启发你探索大语言模型和智能问答系统的更多可能性。如果你觉得这篇文章有用,别忘了点赞和收藏!作者gallonyin,持续关注AI自动化。


http://www.ppmy.cn/news/1228478.html

相关文章

uniapp heckbox-group实现多选

文章目录 html 代码JS 代码 混了业务逻辑&#xff0c;谨慎观看 html 代码 <view><!--可滚动视图区域。用于区域滚动 --><scroll-view :style"{ height: clientHeight px }" :scroll-top"scrollTop" scroll-y"true"scrolltouppe…

C#有关里氏替换原则的经典问题答疑

目录 理解创建类型与变量类型很关键 先来理解变量类型。 再来理解创建类型。 有了正确的理解再来看疑问 里氏替换原则是面向对象七大原则中最重要的原则。 语法表现&#xff1a;父类容器装子类对象。 namespace 里氏替换原则 {class GameObject { } class Player : GameO…

Linux管道的工作过程

常用的匿名管道&#xff08;Anonymous Pipes&#xff09;&#xff0c;也即将多个命令串起来的竖线。管道的创建&#xff0c;需要通过下面这个系统调用。 int pipe(int fd[2]) 我们创建了一个管道 pipe&#xff0c;返回了两个文件描述符&#xff0c;这表示管道的两端&#xff…

在Java代码中指定用JAXB的XmlElement注解的元素的顺序

例如&#xff0c;下面的类RegisterResponse 使用了XmlRootElement注解&#xff0c;同时也使用XmlType注解&#xff0c;并用XmlType注解的propOrder属性&#xff0c;指定了两个用XmlElement注解的元素出现的顺序&#xff0c;先出现flag&#xff0c;后出现enterpriseId&#xff0…

【c++随笔13】多态

【c随笔13】多态 多态性&#xff08;Polymorphism&#xff09;在面向对象编程中是一个重要概念&#xff0c;它允许以统一的方式处理不同类型的对象&#xff0c;并在运行时动态确定实际执行的方法或函数。一、什么是多态性&#xff1f;1、关键概念&#xff1a;C的多态性2、多态定…

高精度算法【Java】(待更新中~)

高进度加法 在Java中可以使用BigInteger进行高精度计算&#xff0c;除此也可以仿照竖式相加的计算原理进行计算。 BigInteger 提供所有 Java 的基本整数操作符的对应物&#xff0c;并提供 java.lang.Math 的所有相关方法。另外&#xff0c;BigInteger 还提供以下运算&#xff1…

【自然语言处理】【大模型】赋予大模型使用工具的能力:Toolformer与ART

赋予大模型使用工具的能力&#xff1a;Toolformer与ART ​ 本文介绍两种赋予大模型使用外部工具能力的方法&#xff1a;Toolformer和ART。 Toolformer论文地址&#xff1a;https://arxiv.org/pdf/2302.04761.pdf ART论文地址&#xff1a;https://arxiv.org/pdf/2303.09014.pd…

开源更安全? yum源配置/rpm 什么是SSH?

文章目录 1.开放源码有利于系统安全2.yum源配置&#xff0c;这一篇就够了&#xff01;(包括本地&#xff0c;网络&#xff0c;本地共享yum源)3.rpm包是什么4.SSH是什么意思&#xff1f;有什么功能&#xff1f; 1.开放源码有利于系统安全 开放源码有利于系统安全 2.yum源配置…