前言
隨著人工智能技術的不斷進步,大語言模型(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自動化。