成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

都在搞MCP,但是我還是要講一下大模型的函數調用

發布于 2025-6-19 07:16
瀏覽
0收藏


都在搞MCP,但是我還是要講一下大模型的函數調用-AI.x社區

函數調用(function calling)是一種機制,允許大語言模型(LLM)通過調用外部函數或 API 執行特定的、預定義的任務。可以將其視為一種功能,讓 LLM 將它無法獨立完成的工作“委托”出去。

例如,假設您向 LLM 發送以下提示:“特斯拉當前的股價是多少?”

沒有函數調用的基本 LLM 可能會根據其訓練數據中的模式“幻覺”出一個答案,例如“可能在 200 美元左右”。經過 RLHF 優化的模型可能會更誠實地說:“我沒有實時數據,所以無法告訴你。”

讓我們用 Qwen2.5 0.5B Instruct 快速嘗試一下:

from transformers importAutoTokenizer,AutoModelForCausalLM


model_name ="Qwen/Qwen2.5-0.5B-Instruct"


model =AutoModelForCausalLM.from_pretrained(model_name)
tokenizer =AutoTokenizer.from_pretrained(model_name)


prompt ="特斯拉當前的股價是多少?"


inputs = tokenizer(prompt, return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=30, do_sample=True)
print(tokenizer.decode(outputs[0]))

輸出:

特斯拉當前的股價是多少?
抱歉,作為一個 AI 語言模型,我無法訪問實時金融數據。特斯拉的股價可能會快速變化。

正如預期,Qwen 表示它不知道,這與任何優秀的指令模型一致。

但通過函數調用,LLM 可以識別對實時股價數據的需求,觸發對金融服務的 API 調用,然后生成類似“截至此刻,特斯拉的股價為 279.24 美元”的回答。

顯然,函數調用是釋放 LLM 全部潛力的關鍵功能,了解如何使用它至關重要。

現在,像 OpenAI GPT-4 這樣的專有模型通過 OpenAI API 原生支持函數調用。它們使用起來更簡單,因為一切都在 OpenAI 生態系統中處理。

Mistral AI 的許多模型(如 Mistral Small 或 Mistral Nemo)也是如此,這些模型是開源的,但也通過 API 提供。

讓我展示一個使用最新 Mistral Small 的函數調用示例。您需要一個 Mistral API 密鑰來運行此示例。

順便說一句,Mistral 的模型被嚴重低估。只要用幾次,你就會發現它們有多優秀。

首先,安裝 Mistral AI 的 Python 客戶端:

pip3 install mistralai
pip3 list | grep mistralai

輸出:

mistralai  1.6.0

接下來,我們需要一個 LLM 可以調用的函數。我將使用 Flask 將該函數作為 REST 端點提供,該函數僅列出本地文件系統中指定目錄的所有文件。

from flask importFlask, request
from os import path, listdir


app =Flask(__name__)


@app.route('/files')
def list_files():
    directory = request.args.get('directory','.')
    files =(
[{'name': f}for f in listdir(directory)
if path.isfile(path.join(directory, f))
]
)
return files


if __name__ =='__main__':
    app.run(host='0.0.0.0', port=8000)

您可以使用 curl 從命令行測試此端點,或者使用您喜歡的瀏覽器。

curl "http://localhost:8000/files?directory=/tmp"

輸出:

[{"name":"api.py"}]

現在,我們需要告訴 LLM 這個函數存在,并且在適當的時候使用它。因為我們仍在使用 Mistral LLM(目前是 mistral-small-2503),這相當簡單。您只需以 LLM 能理解的格式描述該函數。對于大多數 LLM,格式如下:

available_functions =[
{
"type":"function",
"function":{
"name":"files",
"description":"列出目錄中的文件",
"parameters":{
"type":"object",
"properties":{
"directory":{
"type":"string",
"description":"目錄的絕對路徑"
},
},
"required":["directory"]
}
}
}
]

當然,函數描述越詳細、信息量越大,效果越好。

此時,您只需將 ??available_functions?? 數組與提示一起傳遞給客戶端。

from mistralai importMistral
api_key ="..."
model ="mistral-small-2503"


mistral =Mistral(api_key)
response = mistral.chat.complete(
    model = model,
    messages =[
{
"role":"user",
"content":"列出 /tmp 目錄中的所有文件。"
}
],
    tools = available_functions,
    tool_choice ="any"
)


print(response.choices[0].message.tool_calls[0])

輸出:

function=FunctionCall(
  name='files',
  arguments='{"directory": "/tmp"}'
)
id='12bc4' type=None index=0

如您所見,Mistral Small 成功根據給定的提示推斷出需要調用 ??files??? 函數,并使用參數 ??/tmp??。

不過,它不會自己調用函數。這是我們需要做的事情。因此,我們檢查 ??tool_calls?? 數組,如果它不為空,我們就運行 Mistral 希望我們運行的函數。

在我們的例子中,因為我們有一個 REST 端點,我們可以使用 ??requests?? 庫進行 GET 請求。

import json
import requests


if response.choices[0].message.tool_calls:
    tool_call = response.choices[0].message.tool_calls[0]
if tool_call.function.name =="files":
        output = requests.get(
"http://localhost:8000/files?directory="+
            json.loads(
                tool_call.function.arguments
)["directory"]
).json()
print(output)

輸出:

[{'name':'qq1.html'}]

請注意,參數目前是以字符串形式到達,我們需要先將其轉換為 JSON。這就是代碼中包含 ??json.loads()?? 的原因。

還值得注意的是,LL彼此之間,LLM 在這里沒有生成文本。輸出到標準輸出(stdout)應該是您的函數。

很好,現在我們知道如何使用通過 API 訪問的 LLM 進行函數調用。

在本文的其余部分,我們將使用可以本地運行的開源模型。許多這些模型支持函數調用,但使用該功能需要額外步驟。您會發現,這些模型照常生成 token,作為開發者的您需要解析、解釋并使用這些 token 來觸發函數。

讓我們看看是否可以直接將 ??available_functions?? 數組傳遞給 Llama 3.2–1B Instruct 以使其調用我們的函數。

我們首先加載模型:

from transformers importAutoTokenizer,AutoModelForCausalLM


model_name ="meta-llama/Llama-3.2-1B-Instruct"
model =AutoModelForCausalLM.from_pretrained(model_name)
tokenizer =AutoTokenizer.from_pretrained(model_name)

接下來,我們需要將提示包裝在聊天模板中,而不是直接傳遞給模型。聊天模板應包含 ??available_functions?? 數組,以指定模型可以使用的工具。

messages =[
{"


role": "system", "content": "你是一個有用的助手。"},
{"role":"user","content":"/tmp 目錄中有哪些文件?"},
]
template= tokenizer.apply_chat_template(
    messages, tools=available_functions,
    tokenize=False
)

最后,我們對模板進行 token 化,并將其作為輸入傳遞給模型。

inputs = tokenizer(template, return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=30, do_sample=True)
print(tokenizer.decode(outputs[0]))

輸出:

...
...
<|python_tag|>
{"type":"function","function":"files",
"parameters":{"directory":"/tmp"}}
<|eom_id|>

看起來 Llama 3.2 也成功識別了函數調用。這很好!但函數調用目前只是一個(JSON 格式的)字符串,被 ??<|python_tag|>??? 和 ??<|eom_id|>??? 包裹。??eom_id?? 只是一個特殊的消息結束 token。

提取模型輸出的函數調用有很多方法。我將保持簡單,使用正則表達式。

import json
import re
generated_text = tokenizer.decode(outputs[0])


matched = re.search(
    r"<\|python_tag\|>(.*?)<\|eom_id\|>",
    generated_text, re.DOTALL
)
function_call = json.loads(matched.group(1).strip())
print(function_call)

輸出:

{'type':'function','function':'files',
'parameters':{'directory':'/tmp'}}

現在您知道如何使用 Llama 進行函數調用。

如果從 Llama 切換到 Qwen,變化不大。但 Qwen 使用一組不同的 token 來包裹函數調用。以下是 Qwen 的輸出:

<|im_start|>assistant
<tool_call>
{"name":"files","arguments":{"directory":"/tmp"}}
</tool_call><|im_end|>

因此,您的正則表達式需要稍作調整以處理這種新格式。

本文轉載自????PyTorch研習社????,作者:PyTorch研習社

收藏
回復
舉報
回復
相關推薦
主站蜘蛛池模板: 日韩一区二区视频 | 国产一区二区在线播放 | 久久免费精品 | 国产精品亚洲一区 | 亚洲国产成人精品女人久久久 | 成人国产精品久久久 | 黄色大片毛片 | 日韩精品影院 | 亚洲精品白浆高清久久久久久 | 久久久国产一区二区三区 | 欧美一级在线 | 欧美日韩中文字幕在线播放 | 国产激情三区 | 日韩福利在线 | 在线视频一区二区 | 中文二区 | 国产中的精品av涩差av | 日韩成人精品 | 91精品国产91久久综合桃花 | 国产一区二区三区 | 欧美性区 | 久久成人人人人精品欧 | 日韩欧美国产一区二区 | 欧美天堂一区 | 久草免费在线视频 | aaaa日韩| 国产精品美女久久久久aⅴ国产馆 | 亚洲成人三级 | k8久久久一区二区三区 | 在线观看日韩 | 成人做爰www免费看视频网站 | 亚洲精选一区二区 | 免费激情 | 国产精品视频一二三区 | 久久av一区| 中文字幕一区二区三区四区 | 久久久高清 | 亚洲成人日韩 | 国产综合精品一区二区三区 | 激情六月丁香 | 日韩中文字幕在线观看视频 |