大模型 Function Call介紹

什么是Function Call

????????簡(jiǎn)單來說,就是大模型函數(shù)調(diào)用,不是你直接調(diào)用大模型函數(shù),而是你告訴大模型一個(gè)函數(shù),大模型根據(jù)你喂給它的數(shù)據(jù)和參數(shù)執(zhí)行函數(shù)調(diào)用返回給你想要的函數(shù)執(zhí)行結(jié)果。
????????你可以借助大模型的自然語(yǔ)言理解能力實(shí)現(xiàn)自然語(yǔ)言的函數(shù)調(diào)用。大模型這一能力大大增加了私有定制模型的擴(kuò)展性!

為什么有Function Call

  1. 大模型的缺陷:
  • 有所不知
    a.訓(xùn)練數(shù)據(jù)不可能什么都有;垂直、非公開數(shù)據(jù)必有欠缺。
    b.不知道最新信息;大模型的訓(xùn)練周期很長(zhǎng),且更新一次耗資巨大,還有越訓(xùn)越傻的風(fēng)險(xiǎn)。所以它不可能實(shí)時(shí)訓(xùn)練。
  • 沒有"真邏輯"
    它表現(xiàn)出的邏輯、推理,是訓(xùn)練文本的統(tǒng)計(jì)規(guī)律,而不是真正的邏輯,所以有幻覺。
  1. 大模型的優(yōu)勢(shì):
  • 強(qiáng)大的語(yǔ)義泛化能力,能根據(jù)所說的話,識(shí)別出意圖
  • 希望通過大模型來做更多的事,而不僅是簡(jiǎn)單的搜索和閑聊

因?yàn)椋捍竽P托枰B接真實(shí)世界,并對(duì)接真邏輯系統(tǒng)。
Function Call 技術(shù)可以把大模型和業(yè)務(wù)系統(tǒng)連接,實(shí)現(xiàn)更豐富的功能

Function call工作流程

  • 用戶提出functions需求: 用戶用自然語(yǔ)言描述他們想要完成的任務(wù)。
  • LLM理解意圖: 大模型分析用戶的語(yǔ)言,理解其意圖,并將其轉(zhuǎn)化為結(jié)構(gòu)化的請(qǐng)求。
  • 選擇合適的function: 根據(jù)用戶的需求,從預(yù)先定義好的functions中選擇合適的function。
  • 參數(shù)轉(zhuǎn)換與執(zhí)行: 將用戶的需求轉(zhuǎn)化為function能夠理解的參數(shù),并調(diào)用外部工具執(zhí)行操作。
  • 結(jié)果處理與呈現(xiàn): 接收外部工具返回的結(jié)果, 由LLM將其轉(zhuǎn)化為用戶友好的自然語(yǔ)言回應(yīng)。
Function call.png

對(duì)大模型的要求

  • 好的語(yǔ)義理解能力,能夠正確識(shí)別是否調(diào)用function、調(diào)用哪個(gè)function 以及對(duì)應(yīng)參數(shù);
  • 對(duì)于缺失的參數(shù)要能主動(dòng)提問;

langchain實(shí)現(xiàn)

????????當(dāng)今大部分模型廠商都有支持function call的模型,需要選擇對(duì)應(yīng)的正確模型,定義好模型廠商對(duì)應(yīng)的functions書寫規(guī)范,function描述的必備要素:

  • 函數(shù)名
  • 函數(shù)的功能描述
  • 函數(shù)的請(qǐng)求參數(shù)說明
  • 函數(shù)的響應(yīng)參數(shù)說明(可選)

實(shí)例如下:

1. 定義functions

functions = [
    {
        "type":"function",
        "function":{
            "name": "get_current_speed",
            "description": "Gets current speed of a given car",
            "parameters": {
                "type": "object",
                "properties": {
                    "car_name": {
                        "type": "string",
                        "description": "The name of the car"
                    }
                },
                "required": ["car_name"]
            }
        }
       
    },
    {
        "type":"function",
        "function":{
            "name": "get_interior_temperature",
            "description": "Gets the interior temperature of a given car",
            "parameters": {
                "type": "object",
                "properties": {
                    "car_name": {
                        "type": "string",
                        "description": "The name of the car"
                    }
                },
                "required": ["car_name"]
            }
        } 
    },
    {
        "type":"function",
       "function":{
            "name": "get_remaining_battery",
            "description": "Gets the remaining battery of a given car",
            "parameters": {
                "type": "object",
                "properties": {
                    "car_name": {
                        "type": "string",
                        "description": "The name of the car"
                    }
                },
                "required": ["car_name"]
            }
       }
    }
]

2. 創(chuàng)建llm client

import os
import openai
import numpy as np
import json
import tenacity
from openai import OpenAI

client = OpenAI(
    api_key='sk-xxxxxxxxxxxx',
    base_url='https://api.chatanywhere.tech/v1'
)

GPT_MODEL = "gpt-3.5-turbo"

3. 定義Api調(diào)用接口

def generate_response_with_function_call(messages):
    try:
        response = client.chat.completions.create(
            model= GPT_MODEL,
            messages= messages,
            max_tokens=100,  # 生成的最大token數(shù)
            temperature=0.7,  # 生成的隨機(jī)性
            tools=functions,  # 定義的函數(shù)調(diào)用規(guī)范
            tool_choice="auto",
        )
        return response.choices[0].message
           
    except Exception as e:
        print(f"Error generating response: {str(e)}")
        return None

4. 調(diào)用函數(shù)及結(jié)果處理

  • 封裝messages
messages= [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "Car A 當(dāng)前速度是多少"}
]
  • 定義本地function
def get_current_speed(car_name):
   //調(diào)用其他接口來獲取speed

def get_interior_temperature(car_name):
     //調(diào)用其他接口來獲取interior temperature

def get_remaining_battery(car_name): 
    //調(diào)用其他接口來獲取remaining battery
  • 執(zhí)行Api調(diào)用及結(jié)果處理
first_response_message = generate_response_with_function_call(messages)

????????第一次請(qǐng)求大模型接口后,會(huì)從定義的functions里面輸出對(duì)應(yīng)的function信息:

//獲取function name
response_function_name = first_response_message.tool_calls[0].function.name

//獲取function arguments
response_function_argu = json.loads(first_response_message.tool_calls[0].function.arguments)

????????根據(jù)function name及arguments選擇調(diào)用對(duì)應(yīng)的本地function來獲取到當(dāng)前結(jié)果:

# 定義一個(gè)函數(shù)來基于大模型的調(diào)用結(jié)果,來執(zhí)行函數(shù)
def call_function(function_name, arguments):
        if function_name == "get_interior_temperature":
            car_name = arguments.get("car_name")
            return get_interior_temperature(car_name)
        elif function_name == "get_current_speed":
            car_name = arguments.get("car_name")
            return get_current_speed(car_name)
        elif function_name == "get_remaining_battery":
            car_name = arguments.get("car_name")
            return get_remaining_battery(car_name)
        return "Function not found"

# 執(zhí)行本地函數(shù)
function_response = call_function(response_function_name, response_function_argu)

????????將獲得的函數(shù)執(zhí)行結(jié)果補(bǔ)充進(jìn)messages,再次調(diào)用API:

messages.append(first_response_message)
messages.append({
    "role":"tool",
    "content":function_response,
    "tool_call_id":response_message.tool_calls[0].id,
})

second_response = generate_response_with_function_call(messages)

# 讀取二次調(diào)用得到的content
final_message = second_response.content
print("最終輸出: " + str(final_message))

最終輸出: Car A當(dāng)前車速為70.0km/h

????????經(jīng)過兩次大模型的API調(diào)用,得到了合理的結(jié)果;

  • 第一次大模型調(diào)用:根據(jù)用戶的query及定義的functions,得到對(duì)應(yīng)的function name及arguments
  • 第二次大模型調(diào)用:結(jié)合外部請(qǐng)求結(jié)果,大模型進(jìn)行總結(jié)給出合理的回答
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評(píng)論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評(píng)論 3 417
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評(píng)論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評(píng)論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,761評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,782評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,983評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,222評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評(píng)論 1 286
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,678評(píng)論 3 392
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,978評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容