大模型工具調(diào)用(function call)原理
發(fā)布日期:2023/11/5 23:10:41 瀏覽量:
使用Function Call功能時(shí),你需要定義(并不是真的寫程序去定義一個(gè)函數(shù),而僅僅是用文字來描述一個(gè)函數(shù))一些function(需要指定函數(shù)名,函數(shù)用途的描述,參數(shù)名,參數(shù)描述),傳給LLM,當(dāng)用戶輸入一個(gè)問題時(shí),LLM通過文本分析是否需要調(diào)用某一個(gè)function,如果需要調(diào)用,那么LLM返回一個(gè)json,json包括需要調(diào)用的function名,需要輸入到function的參數(shù)名,以及參數(shù)值。總而言之,function call幫我們做了兩件事情:1.判斷是否要調(diào)用某個(gè)預(yù)定義的函數(shù)。2.如果要調(diào)用,從用戶輸入的文本里提取出函數(shù)所需要的函數(shù)值。
通過查詢天氣舉個(gè)例子,這塊我用openai的funciton call進(jìn)行演示,chatglm3的權(quán)重還沒有下完hhh:
首先我們定義一些function,如下所示,我只定義了一個(gè)查詢天氣的函數(shù)get_current_weather,我們需要對(duì)這個(gè)函數(shù)進(jìn)行簡(jiǎn)單的描述,如“獲取今天的天氣”。這個(gè)函數(shù)有兩個(gè)參數(shù),分別是地點(diǎn)location和時(shí)間time,也需要進(jìn)行文本描述。LLM根據(jù)函數(shù)描述,參數(shù)描述以及用戶的輸入,來決定是不是要調(diào)用這個(gè)funciton。
func = {
"name": "get_current_weather",
"description": "獲取今天的天氣",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "獲取天氣情況的城市或者國家,比如北京、東京、新加坡"
},
"time": {
"type": "string",
"description": "時(shí)間信息"
},
},
"required": ["location", "time"]
}
}
當(dāng)我們?cè)趏penai的請(qǐng)求里添加了funtions相關(guān)的字段,他會(huì)增加一個(gè)判斷是否需要調(diào)用function的環(huán)節(jié)。
以下以向ChatGPT輸入“10月27日北京天氣怎么樣”為例:
請(qǐng)求里沒有functions字段得到的結(jié)果如下,他會(huì)告訴你一大段答案(應(yīng)該是假的),就是走Chatgpt正常的回答。
根據(jù)天氣預(yù)報(bào),10月27日北京的天氣預(yù)計(jì)為晴到多云,氣溫較低。最高氣溫約為16攝氏度,最低氣溫約為4攝氏度。需要注意保暖措施,適時(shí)添衣物。’, message=AIMessage(content=’根據(jù)天氣預(yù)報(bào),10月27日北京的天氣預(yù)計(jì)為晴到多云,氣溫較低。最高氣溫約為16攝氏度,最低氣溫約為4攝氏度。需要注意保暖措施,適時(shí)添衣物?!?/pre>
請(qǐng)求里如果有functions字段,返回了一個(gè)json,并幫我們從輸入文本里抽取了get_current_weather所需要的location和time的函數(shù)值(因?yàn)閏hatgpt訓(xùn)練數(shù)據(jù)截至到2021年,它還幫忙腦補(bǔ)了個(gè)年份hhh)。
{’name’: ’get_current_weather’, ’arguments’: ’{\n "location": "北京",\n "time": "2021-10-27"\n}’}
本質(zhì)上ChatGPT不就是在幫我們?cè)谧?/span>個(gè)文本結(jié)構(gòu)化嘛,這個(gè)有啥用呢?我們知道,ChatGPT并不能幫我們真正的去查詢天氣,但是我們可以真的用python去定義一個(gè)get_current_weather函數(shù),在這個(gè)函數(shù)里,編寫程序(調(diào)用查詢天氣的工具包)去實(shí)現(xiàn)查詢天氣的功能,函數(shù)的輸入就用ChatGPT返回的json里的內(nèi)容,相當(dāng)于我們通過編程幫ChatGPT提供了一個(gè)查詢天氣的工具,因此也可以管function call叫做“工具調(diào)用”。get_current_weather返回天氣信息給ChatGPT,ChatGPT再回答給用戶。整體流程如下圖所示。我們可以定義各種功能的函數(shù)幫ChatGPT完成任務(wù),比如查詢網(wǎng)頁,算數(shù)等,因此工具調(diào)用對(duì)于agent來說非常重要。
chatglm3 function call實(shí)現(xiàn)原理
把chatglm2和chatglm3模型文件diff一下就能發(fā)現(xiàn),代碼改動(dòng)很少,增加了幾個(gè)新的token,增加一些處理function字符串的邏輯。chatglm3官方function call示例如下,和chatgpt 定義的function結(jié)構(gòu)幾乎就是一致的。將包含函數(shù)描述的system_info 變量通過history傳入到LLM的chat接口里。
tools = [
{
"name": "track",
"description": "追蹤指定股票的實(shí)時(shí)價(jià)格",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"description": "需要追蹤的股票代碼"
}
},
"required": [’symbol’]
}
},
{
"name": "text-to-speech",
"description": "將文本轉(zhuǎn)換為語音",
"parameters": {
"type": "object",
"properties": {
"text": {
"description": "需要轉(zhuǎn)換成語音的文本"
},
"voice": {
"description": "要使用的語音類型(男聲、女聲等)"
},
"speed": {
"description": "語音的速度(快、中等、慢等)"
}
},
"required": [’text’]
}
}
]
system_info = {"role": "system", "content": "Answer the following questions as best as you can. You have access to the following tools:", "tools": tools}
history = [system_info]
query = "幫我查詢股票10111的價(jià)格"
response, history = model.chat(tokenizer, query, history=history)
print(response)
接下來,chatglm3的chat接口調(diào)用了tokenization_chatglm.py里邊的build_chat_input函數(shù),處理history的內(nèi)容,具體代碼如下。嗯,就是直接把json格式的函數(shù)描述(存在item["tools"]里)直接轉(zhuǎn)換成了字符串,然后和其他輸入一并送入LLM,就是這么簡(jiǎn)單。歸根到底function call能力就是在prompt上邊做了手腳。那為什么chatglm3比別的模型更加強(qiáng)調(diào)自己工具調(diào)用能力強(qiáng)呢?當(dāng)然是微調(diào)時(shí)候有function call格式的數(shù)據(jù)啦!
def build_chat_input(self, query, history=None, role="user"):
if history is None:
history = []
input_ids = []
for item in history:
content = item["content"]
if item["role"] == "system" and "tools" in item:
content = content + "\n" + json.dumps(item["tools"], indent=4, ensure_ascii=False)
input_ids.extend(self.build_single_message(item["role"], item.get("metadata", ""), content))
input_ids.extend(self.build_single_message(role, "", query))
input_ids.extend([self.get_command("<|assistant|>")])
return self.batch_encode_plus([input_ids], return_tensors="pt", is_split_into_words=True)
馬上咨詢: 如果您有業(yè)務(wù)方面的問題或者需求,歡迎您咨詢!我們帶來的不僅僅是技術(shù),還有行業(yè)經(jīng)驗(yàn)積累。
QQ: 39764417/308460098 Phone: 13 9800 1 9844 / 135 6887 9550 聯(lián)系人:石先生/雷先生