該解決方案基于大語言模型(LLM)的意圖識別技術,能夠從海量的數據中學習到復雜的語言規律和用戶行為模式,實現對用戶意圖的更精準識別和更自然流暢的交互體驗。本方案以通義千問1.5(Qwen1.5)大語言模型為基礎,為您介紹基于LLM的意圖識別解決方案的完整開發流程。
背景信息
什么是意圖識別
即AI智能體通過理解人們用自然語言所表達的需求,來執行相應的操作或提供相應的信息,它是智能交互系統中不可或缺的一環。目前,基于大語言模型(LLM)的意圖識別技術已經得到業界的廣泛關注,并被廣泛應用。
意圖識別技術的典型場景示例
在智能語音助手領域,用戶通過簡單的語音命令與語音助手進行交互。例如,當用戶對語音助手說“我想聽音樂”時,系統需要準確識別出用戶的需求是播放音樂,然后執行相應操作。
在智能客服場景中,挑戰則體現在如何處理各種客戶服務請求,并將它們快速準確地分類至例如退貨、換貨、投訴等不同的處理流程中。例如,在電子商務平臺上,用戶可能會表達“我收到的商品有瑕疵,我想要退貨”。在這里,基于LLM的意圖識別系統要能夠迅速捕捉到用戶的意圖是“退貨”,并且自動觸發退貨流程,進一步引導用戶完成后續操作。
使用流程
基于LLM的意圖識別解決方案的使用流程如下:
您可以參照數據格式要求和數據準備策略并針對特定的業務場景準備相應的訓練數據集。您也可以參照數據準備策略準備業務數據,然后通過智能標注(iTAG)進行原始數據標注。導出標注結果,并轉換為PAI-QuickStart支持的數據格式,用于后續的模型訓練。
在快速開始(QuickStart)中,基于Qwen1.5-1.8B-Chat模型進行模型訓練。模型訓練完成后,對模型進行離線評測。
當模型評測結果符合您的預期后,通過快速開始(QuickStart)將訓練好的模型部署為EAS在線服務。
前提條件
在開始執行操作前,請確認您已完成以下準備工作:
已開通PAI(DLC、EAS)后付費,并創建默認工作空間,詳情請參見開通PAI并創建默認工作空間。
已創建OSS存儲空間(Bucket),用于存儲訓練數據和訓練獲得的模型文件。關于如何創建存儲空間,詳情請參見控制臺創建存儲空間。
準備訓練數據
支持使用以下兩種方式準備訓練數據:
方式二:依據數據準備策略,使用iTAG平臺進行數據標注。適用于大規模數據場景,顯著提升標注效率。
數據準備策略
為了提升訓練的有效性和穩定性,您可以參考以下策略準備數據:
對于單意圖識別場景,確保每類意圖的標注數量至少為50至100條,當模型微調效果不佳時,您可以考慮增加標注數據量。同時,您需要注意每類意圖的標注數據量盡量均衡,不宜出現某類意圖的標注數據量過多的情況。
對于多意圖識別場景或多輪對話場景,建議標注數據量在單意圖識別場景數據量的20%以上,同時多意圖識別場景或多輪對話場景涉及的意圖需要在單意圖識別場景中出現過。
意圖描述需要覆蓋盡可能豐富的問法和場景。
數據格式要求
訓練數據格式要求為:JSON格式的文件,包含instruction和output兩個字段,分別對應輸入的指令和模型預測的意圖以及對應的關鍵參數。對于不同的意圖識別場景,相應的訓練數據示例如下:
對于單意圖識別場景,您需要針對特定的業務場景,準備相應的業務數據,用于大語言模型(LLM)的微調訓練。以智能家居的單輪對話為例,訓練數據示例如下:
[ { "instruction": "我想聽音樂", "output": "play_music()" }, { "instruction": "太吵了,把聲音開小一點", "output": "volume_down()" }, { "instruction": "我不想聽了,把歌關了吧", "output": "music_exit()" }, { "instruction": "我想去杭州玩,幫我查下天氣預報", "output": "weather_search(杭州)" }, ]
對于多意圖識別場景或多輪對話場景,用戶的意圖可能會在多個對話輪次中表達。在這種情況下,您可以準備多輪對話數據,并對多輪用戶的輸入進行標注。以語音助手為例,給定一個多輪對話流:
User:我想聽音樂。 Assistant:什么類型的音樂? User:給我放個***的音樂吧。 Assistant:play_music(***)
相應的多輪對話訓練數據格式如下:
[ { "instruction": "我想聽音樂。給我放個***的音樂吧。", "output": "play_music(***)" } ]
由于多輪對話模型訓練的長度明顯提升,而且在實際應用中,多輪對話意圖識別場景數量有限。建議您僅當單輪對話的意圖識別無法滿足實際業務需求時,考慮應用多輪對話的模型訓練方式。本方案將以單輪對話為例,為您展示該解決方案的整個使用流程。
使用iTAG平臺進行數據標注
您也可以參考以下操作步驟,使用PAI-iTAG平臺對數據進行標注,以生成滿足特定要求的訓練數據集。
將用于iTAG標注的數據注冊到PAI數據集。
參考數據準備策略,準備manifest格式的數據文件,內容示例如下。
{"data":{"instruction": "我想聽音樂"}} {"data":{"instruction": "太吵了,把聲音開小一點"}} {"data":{"instruction": "我不想聽了,把歌關了吧"}} {"data":{"instruction": "我想去杭州玩,幫我查下天氣預報"}}
創建數據集,其中關鍵參數說明如下,其他參數配置詳情,請參見創建及管理數據集。
參數
描述
選擇數據存儲
選擇阿里云對象存儲(OSS)。
屬性
選擇文件。
從阿里云云存儲創建
選擇已創建的OSS目錄,按照以下操作步驟上傳已準備好的manifest文件:
在選擇OSS目錄對話框,單擊上傳文件。
單擊查看本地文件或拖拽上傳文件,根據提示上傳manifest文件。
在智能標注iTAG頁面創建模板,其中關鍵配置說明如下,其他配置詳情,請參見模板管理。
配置
描述
顯示內容
將內容組件下的文本組件拖拽到顯示內容區域,然后單擊文本組件,并在配置面板中,將選擇文本內容所在字段配置為instruction。
全局題目
將題目組件下的填空組件拖拽到全局題目區域,然后單擊填空組件,并在配置面板中,將題目名稱設置為output。
創建標注任務,其中關鍵配置說明如下,其他參數配置詳情,請參見創建標注任務。
參數
描述
輸入數據集
選擇上述步驟已創建的數據集。
說明請注意,輸入的數據和使用的模板對應。
模板類型
選擇自定義模板,并在已有模板下拉框中,選擇已創建的模板。
標注任務創建完成后,開始標注數據。具體操作,請參見處理標注任務。
完成數據標注后,將標注結果導出至OSS目錄中。具體操作,請參見導出標注結果數據。
在本方案中,輸出的manifest文件的內容示例如下,數據格式說明,請參見標注數據格式概述。
{"data":{"instruction":"我想聽音樂","_itag_index":""},"label-1787402095227383808":{"results":[{"questionId":"2","data":"play_music()","markTitle":"output","type":"survey/value"}]},"abandonFlag":0,"abandonRemark":null} {"data":{"instruction":"太吵了,把聲音開小一點","_itag_index":""},"label-1787402095227383808":{"results":[{"questionId":"2","data":"volume_down()","markTitle":"output","type":"survey/value"}]},"abandonFlag":0,"abandonRemark":null} {"data":{"instruction":"我不想聽了,把歌關了吧","_itag_index":""},"label-1787402095227383808":{"results":[{"questionId":"2","data":"music_exit()","markTitle":"output","type":"survey/value"}]},"abandonFlag":0,"abandonRemark":null} {"data":{"instruction":"我想去杭州玩,幫我查下天氣預報","_itag_index":""},"label-1787402095227383808":{"results":[{"questionId":"2","data":"weather_search(杭州)","markTitle":"output","type":"survey/value"}]},"abandonFlag":0,"abandonRemark":null}
在終端中,使用如下Python腳本,將上述生成的manifest格式的數據標注結果文件,轉換為適用于快速開始(QuickStart)的訓練數據格式。
import json # 輸入文件路徑和輸出文件路徑。 input_file_path = 'test_json.manifest' output_file_path = 'train.json' converted_data = [] with open(input_file_path, 'r', encoding='utf-8') as file: for line in file: data = json.loads(line) instruction = data['data']['instruction'] for key in data.keys(): if key.startswith('label-'): output = data[key]['results'][0]['data'] converted_data.append({'instruction': instruction, 'output': output}) break with open(output_file_path, 'w', encoding='utf-8') as outfile: json.dump(converted_data, outfile, ensure_ascii=False, indent=4)
輸出結果為JSON格式的文件。
訓練及離線評測模型
訓練模型
快速開始(QuickStart)匯集了優秀的國內外AI開源社區預訓練模型。您可以在快速開始(QuickStart)中,實現從訓練到部署再至推理的完整流程,無需編寫代碼,極大簡化了模型的開發過程。
本方案以Qwen1.5-1.8B-Chat模型為例,為您介紹如何使用已準備好的訓練數據,在快速開始(QuickStart)中進行模型訓練。具體操作步驟如下:
進入快速開始頁面。
登錄PAI控制臺。
在頂部左上角根據實際情況選擇地域。
在左側導航欄選擇工作空間列表,單擊指定工作空間名稱,進入對應工作空間內。
在左側導航欄選擇快速開始。
在快速開始頁面右側的模型列表中,單擊通義千問1.5-1.8B-Chat模型卡片,進入模型詳情頁面。
在模型詳情頁面,單擊右上角的微調訓練。
在微調訓練配置面板中,配置以下關鍵參數,其他參數取默認配置。
參數
描述
訓練方式
訓練方式
全參數微調:資源要求高,訓練時間長,效果一般更好。
說明參數量較小的模型支持全參數微調,請根據您的場景需要進行選擇。
QLoRA:表示輕量化微調。相較于全參數微調,資源要求更低,訓練時間更短,效果一般會差一些。
LoRA:同QLoRA。
數據集配置
訓練數據集
參照以下操作步驟,選擇已準備好的訓練數據集。
在下拉列表中選擇OSS文件或目錄。
單擊按鈕,選擇已創建的OSS目錄。
在選擇OSS目錄或文件對話框中,單擊上傳文件,拖拽上傳已準備好的訓練數據集文件,并單擊確定。
訓練輸出配置
model
選擇OSS目錄,用來存放訓練輸出的配置文件。
超參數配置
關于超參數詳細介紹,請參見表1.全量超參數說明。
建議您按照以下超參數配置策略進行配置,針對不同的訓練方式,關鍵超參數推薦配置,請參見表2.超參數推薦配置。
注意根據不同的訓練方式配置超參數。
全局批次大?。娇〝?per_device_train_batch_size*gradient_accumulation_steps
為了最大化訓練性能,優先調大卡數和per_device_train_batch_size。
一般將全局批次大小設置為64至256,當訓練數據量很少時,可以適當調小。
序列長度(seq_length)可以根據實際場景進行調整。例如,數據集中本文序列最大長度為50,則可以將序列長度設置為64(一般設置為2的次冪數)。
當訓練loss下降過慢或者不收斂時,建議您適當調大學習率(learning_rate)。同時,需要確認訓練數據的數據質量是否有保證。
參數
全參數微調
LoRA/QLoRA
learning_rate
5e-6、5e-5
3e-4
全局批次大小
256
256
seq_length
256
256
num_train_epochs
3
5
lora_dim
0
64
lora_alpha
0
16
load_in_4bit
False
True/False
load_in_8bit
False
True/False
單擊訓練按鈕,在計費提醒對話框中單擊確定。
系統自動跳轉到訓練任務詳情頁面,訓練任務啟動成功,您可以在該頁面查看訓練任務狀態和訓練日志。
離線評測模型
當模型訓練結束后,您可以在終端使用Python腳本,來評測模型效果。
準備評測數據文件testdata.json,內容示例如下:
[ { "instruction": "想知道的十年是誰唱的?", "output": "music_query_player(十年)" }, { "instruction": "今天北京的天氣怎么樣?", "output": "weather_search(杭州)" } ]
在終端中,使用如下Python腳本來離線評測模型。
#encoding=utf-8 from transformers import AutoModelForCausalLM, AutoTokenizer import json from tqdm import tqdm device = "cuda" # the device to load the model onto # 修改模型路徑 model_name = '/mnt/workspace/model/qwen14b-lora-3e4-256-train/' print(model_name) model = AutoModelForCausalLM.from_pretrained( model_name, torch_dtype="auto", device_map="auto" ) tokenizer = AutoTokenizer.from_pretrained(model_name) count = 0 ecount = 0 # 修改訓練數據路徑 test_data = json.load(open('/mnt/workspace/data/testdata.json')) system_prompt = '你是一個意圖識別專家,可以根據用戶的問題識別出意圖,并返回對應的函數調用和參數。' for i in tqdm(test_data[:]): prompt = '<|im_start|>system\n' + system_prompt + '<|im_end|>\n<|im_start|>user\n' + i['instruction'] + '<|im_end|>\n<|im_start|>assistant\n' gold = i['output'] gold = gold.split(';')[0] if ';' in gold else gold model_inputs = tokenizer([prompt], return_tensors="pt").to(device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=64, pad_token_id=tokenizer.eos_token_id, eos_token_id=tokenizer.eos_token_id, do_sample=False ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] pred = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] if gold.split('(')[0] == pred.split('(')[0]: count += 1 gold_list = set(gold.strip()[:-1].split('(')[1].split(',')) pred_list = set(pred.strip()[:-1].split('(')[1].split(',')) if gold_list == pred_list: ecount += 1 else: pass print("意圖識別準確率:", count/len(test_data)) print("參數識別準確率:", ecount/len(test_data))
部署及調用模型服務
部署模型服務
當評測模型效果符合預期時,您可以按照以下操作步驟,將訓練獲得的模型部署為EAS在線服務。
在任務詳情頁面的模型部署區域,系統已默認配置了模型服務信息和資源部署信息,您也可以根據需要進行修改,參數配置完成后單擊部署按鈕。
在計費提醒對話框中,單擊確定。
系統自動跳轉到部署任務頁面,當狀態為運行中時,表示服務部署成功。
在語音助手的意圖識別場景中,為了保證用戶的交互體驗,通常要求更高的延時。因此建議您使用PAI提供的BladeLLM推理引擎進行LLM服務的部署,詳情請參見如何提升推理并發且降低延遲?。
調用模型服務
服務部署成功后,您可以在服務詳情頁面右側,單擊查看WEB應用,使用ChatLLM WebUI進行實時交互,也可以使用API進行模型推理。具體使用方法參考5分鐘使用EAS一鍵部署LLM大語言模型應用。
以下提供一個示例,展示如何通過客戶端發起Request調用:
獲取服務訪問地址和Token。
在服務詳情頁面,單擊資源信息區域的查看調用信息。
在調用信息對話框中,查詢服務訪問地址和Token,并保存到本地。
在終端中,執行如下代碼調用服務。
import argparse import json from typing import Iterable, List import requests def post_http_request(prompt: str, system_prompt: str, history: list, host: str, authorization: str, max_new_tokens: int = 2048, temperature: float = 0.95, top_k: int = 1, top_p: float = 0.8, langchain: bool = False, use_stream_chat: bool = False) -> requests.Response: headers = { "User-Agent": "Test Client", "Authorization": f"{authorization}" } pload = { "prompt": prompt, "system_prompt": system_prompt, "top_k": top_k, "top_p": top_p, "temperature": temperature, "max_new_tokens": max_new_tokens, "use_stream_chat": use_stream_chat, "history": history } response = requests.post(host, headers=headers, json=pload, stream=use_stream_chat) return response def get_response(response: requests.Response) -> List[str]: data = json.loads(response.content) output = data["response"] history = data["history"] return output, history if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--top-k", type=int, default=4) parser.add_argument("--top-p", type=float, default=0.8) parser.add_argument("--max-new-tokens", type=int, default=2048) parser.add_argument("--temperature", type=float, default=0.95) parser.add_argument("--prompt", type=str, default="How can I get there?") parser.add_argument("--langchain", action="store_true") args = parser.parse_args() prompt = args.prompt top_k = args.top_k top_p = args.top_p use_stream_chat = False temperature = args.temperature langchain = args.langchain max_new_tokens = args.max_new_tokens host = "EAS服務公網地址" authorization = "EAS服務公網Token" print(f"Prompt: {prompt!r}\n", flush=True) # 在客戶端請求中可設置語言模型的system prompt。 system_prompt = "你是一個意圖識別專家,可以根據用戶的問題識別出意圖,并返回對應的意圖和參數" # 客戶端請求中可設置對話的歷史信息,客戶端維護當前用戶的對話記錄,用于實現多輪對話。通常情況下可以使用上一輪對話返回的histroy信息,history格式為List[Tuple(str, str)]。 history = [] response = post_http_request( prompt, system_prompt, history, host, authorization, max_new_tokens, temperature, top_k, top_p, langchain=langchain, use_stream_chat=use_stream_chat) output, history = get_response(response) print(f" --- output: {output} \n --- history: {history}", flush=True) # 服務端返回JSON格式的響應結果,包含推理結果與對話歷史。 def get_response(response: requests.Response) -> List[str]: data = json.loads(response.content) output = data["response"] history = data["history"] return output, history
其中:
host:配置為已獲取的服務訪問地址。
authorization:配置為已獲取的服務Token。
相關文檔
更多關于iTAG的使用流程以及標注數據格式要求,請參見智能標注(iTAG)。
更多關于EAS產品的內容介紹,請參見模型在線服務(EAS)。
使用快速開始(QuickStart)功能,您可以輕松完成更多場景的部署與微調任務,包括Llama-3、Qwen1.5、Stable Diffusion V1.5等系列模型。詳情請參見場景實踐。