函数调用是指能够可靠地将大语言模型(LLM)连接到外部工具,以实现有效的工具使用和与外部API的交互。函数调用,也称为工具使用或API调用,是一种技术,允许LLM与外部系统、API和工具进行交互。通过向模型提供一组函数或工具及其描述和使用说明,模型可以智能地选择和调用适当的函数以完成给定的任务。
像GPT-4和GPT-3.5这样的大型语言模型经过微调以检测何时需要调用函数,并输出包含调用函数所需参数的JSON。通过函数调用机制被调用的函数将在您的AI应用程序中作为工具使用,并且您可以在单个请求中定义多个函数。
调用函数是构建由LLM驱动的聊天机器人或代理的重要能力,这些机器人或代理需要检索上下文信息或通过将自然语言转换为API请求来与外部工具交互。
- 函数调用:此技术涉及LLM确定提示是否需要调用特定功能,然后使用必要的参数调用该功能。该功能可以是提供所需数据或功能以生成响应的预定义工具或API,例如天气查询或信息检索。
- 函数定义:函数被定义为可以由LLM调用的工具或API,这些工具或API通常具有特定的名称和需要传递的参数集以执行功能。例如,一个用于检索给定位置当前天气的函数可能需要参数,如城市名称和度量单位。
- 函数调用的工作流程包括以下步骤:
-
步骤 1:用户发送可能需要调用函数的提示。
-
步骤 2:应用程序将提示以及可用函数及其输入模式或结构发送给LLM。
-
步骤 3:LLM确定提示是否需要调用函数,并用包含需要调用的函数及其输入参数的JSON格式的字典进行响应。
- 步骤 4:应用程序解析LLM的回复,调用函数,并将输出包含在最终回复中。
函数调用功能有各种应用和用例,包括:
- 会话代理:可以通过调用外部API或外部知识库来回答复杂问题,创建复杂的会话代理或聊天机器人,并提供更相关和有用的响应。
- 自然语言理解:可以将自然语言转换为结构化的JSON数据,从文本中提取结构化数据,并执行命名实体识别、情感分析和关键词提取等任务。
- 数学问题求解:可以通过定义自调用函数来解决需要多个步骤和不同类型高级计算的复杂数学问题。
- API集成:可以有效将LLM与外部API集成,以根据输入获取数据或执行操作。这有助于构建问答系统或创意助手,如查询系统或创意助手。
- 信息提取:可以通过调用函数有效从给定输入中提取特定信息,例如从文章中提取相关新闻故事或引用。
函数调用可以与检索增强生成(RAG)集成,从而显著提升基于大语言模型(LLM)的应用程序的能力。基于函数调用的RAG代理利用了这两种方法的优势,利用外部知识库进行准确的数据检索,从而高效完成特定任务。
几个商业和开源的大型语言模型支持函数调用,包括:
- OpenAI 的 GPT-4 和 GPT-3.5 Turbo:这些模型经过微调,能够检测何时需要调用函数,并输出包含调用函数所需参数的 JSON。
- Google Gemini:此模型支持通过 Vertex AI 和 Google AI Studio 进行函数调用。
- Anthropic Claude:此模型提供一个 API,可以提供类似于 OpenAI 模型的函数调用功能。
- Cohere Command:此模型提供一个 API 用于调用函数,允许与外部工具和数据源集成。
- Mistral:此开源模型具备了函数调用能力,允许开发人员定义模型在推理过程中可以调用的自定义函数。
- NexusRaven:此开源模型专门设计用于高级函数调用,在某些调用网络安全工具和 API 的基准测试中甚至超过了 GPT-4。
- Gorilla OpenFunctions:这是一个基于 API 文档进行了微调的 7B 大型语言模型,可以从自然语言提示中生成准确的函数调用和 API 请求。
- Fireworks FireFunction:此开源模型在结构化信息生成和路由决策等实际应用场景中达到了接近 GPT-4 的质量水平。
- Nous Hermes 2 Pro:此模型设计用于高级函数调用,可用于执行命名实体识别和情感分析等任务。
大型语言模型(LLM)通过分析用户提示来确定何时使用函数调用,以检测是否需要执行外部功能或工具。其工作原理如下:
- 用户发送一个可能需要调用函数的提示,例如“纽约市当前的天气是怎样的?”
- 应用程序将提示以及可用函数及其输入模式定义发送给LLM,例如:它会将提示和函数定义一并发送。
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取给定位置的当前天气",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市和州,例如纽约,NY"
}
},
"required": ["location"]
}
}
}
```[1][4]
3. **LLM 分析提示以确定是否需要调用函数**。如果是,它从提供的列表中选择适当的函数,并生成包含函数名称及其输入参数的 JSON 响应[1][5]。
4. **对于天气示例,LLM 将返回**:
```json
{
"function": "get_current_weather",
"arguments": {
"location": "纽约,NY"
}
}
5. 应用程序接着使用该提供的参数执行该函数,并将结果返回给LLM。
6. 最后,LLM 根据函数输出生成对用户原始提示的最终响应
LLM使用自然语言处理来检测到提示需要外部功能时,从提供的列表中选择合适的函数,生成带有参数的功能调用请求,然后将功能输出整合到最终响应中。这使得LLM能够通过与外部工具和API的接口来扩展其功能。
能否提供一些在LLM中需要使用函数的任务示例?
调用函数在大型语言模型(LLMs)中使它们能够与外部工具和API交互,从而扩展其能力,使其不仅限于文本响应。这里有一些示例需要在LLMs中进行函数调用的任务:
- 会话代理:可以通过调用外部API或外部知识库来回答复杂问题,创建复杂的会话代理或聊天机器人,并提供更相关和有用的响应。
- 自然语言理解:可以将自然语言转换为结构化的JSON数据,从文本中提取结构化数据,并执行命名实体识别、情感分析和关键词提取等任务。
- 数学问题求解:可以通过调用函数来定义自定义函数以解决需要多步骤和不同类型高级计算的复杂数学问题。
- API集成:可以有效地将LLM与外部API集成,以根据输入获取数据或执行操作。这有助于构建问答系统或创意助手等应用。
- 信息提取:可以通过调用函数有效地从给定输入中提取特定信息,例如从文章中检索相关新闻故事或引用等信息。
- 发送邮件:LLM可以通过调用函数生成结构化的响应(例如JSON对象),而不是生成文本响应,以执行发送邮件的任务。
- 数据检索:可以通过调用函数来检索实时数据或当前事件,个人信息,如日程安排、电子邮件或待办事项列表中的项目,或业务信息如销售数据、客户信息或支持查询。
- 任务自动化:可以通过定义模型可以使用的自定义函数来调用函数以扩展其功能和知识,例如操作数据并更改或更新存储在其他地方的信息,从而实现任务自动化。
这些任务展示了如何在大规模语言模型中调用功能以实现,弥合自然语言处理与实际任务之间的鸿沟,使这些模型能够与外部系统交互并执行复杂的操作。
大型语言模型(LLMs)在决定调用哪个外部功能时依据什么标准?LLM通过分析用户提示来决定是否调用哪个外部功能,判断是否需要调用外部功能或工具。以下是详细步骤:
以下是步骤分解:
- 用户输入:用户输入或提供一个可能需要调用函数的提示,例如“纽约市的天气如何?”。
- 函数描述:应用程序将提示连同可用函数及其输入参数一起发送给LLM。例如,它会将提示与函数定义一起发送:
{
"type": "function",
"function": {
"name": "get_current_weather",
"description": "获取指定地点的当前天气",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市和州,例如“纽约, NY”"
}
},
"required": ["location"]
}
}
}
- LLM 分析:LLM 分析提示信息以确定是否需要调用函数。如果是,则从提供的函数列表中选择适当的函数,并生成一个包含函数名及其对应输入参数的 JSON 响应。
- 函数选择:LLM 选择一个适合执行用户指令的函数。例如,在天气查询中,LLM 将选择
get_current_weather
函数。 - 函数调用:LLM 返回所选函数名和值给应用程序。应用程序随后执行该函数,并将 API 响应返回给 LLM。
- 响应生成:LLM 使用函数调用的响应来确定提示响应。例如,如果函数调用返回纽约市当前的天气,LLM 将生成如“纽约市当前天气晴朗,最高气温为75华氏度”的响应。
- 最终响应:最终响应通过应用程序返回给用户。此响应是通过结合函数调用的输出和 LLM 对用户意图的理解生成的。
LLM处理模糊的函数调用时,通过使用各种技术来消除函数名称和参数的歧义。以下是一些他们采用的策略:
- 上下文分析:LLM 通过分析函数调用的上下文来确定意图调用的函数。这包括理解用户的意图、对话历史和可用的函数。
- 函数定义:LLM 使用提供的函数定义来确定要调用的正确函数。这包括函数名、描述和参数。如果多个函数具有相同的名称,LLM 可以使用描述和参数来消除歧义性。
- 参数匹配:LLM 将提供的参数与每个函数所需的参数进行匹配。如果一个函数需要特定的参数,并且提供的参数与之匹配,则 LLM 可以确定要调用的正确函数。
- 系统消息:LLM 可以使用系统消息来提供函数调用的额外上下文和约束条件。这些消息可以指定所需的参数、它们的值以及对函数调用的任何约束。
- JSON 模板:LLM 可以使用 JSON 模板来定义函数调用的结构。这包括函数名、参数及其值。然后 LLM 可以使用此模板生成正确的函数调用。
- 函数重载:LLM 可以通过分析函数名和参数来处理函数重载,以确定要调用的正确函数。这包括检查具有相同名称但不同参数的多个函数。
- 命名空间管理:LLM 可以管理命名空间以避免命名空间冲突并确保正确调用函数。这包括将函数组织成逻辑组,并为每个函数使用唯一名称。
- 错误处理:LLM 可以通过提供错误消息并使用正确的参数重新调用函数来处理函数调用期间发生的错误。
通过采用这些策略,LLMs可以有效地处理功能调用的模糊性,并确保使用正确的参数调用正确的功能,使之准确无误。
# 定义函数
def 获取当前天气(location):
# 模拟API调用获取当前天气
weather_data = {
"New York, NY": {"weather": "晴朗", "temperature": 75},
"Los Angeles, CA": {"weather": "多云", "temperature": 65}
}
return weather_data.get(location, {"weather": "未知", "temperature": "未知"})
def 获取股票价格(ticker):
# 模拟API调用获取股票价格
stock_data = {
"AAPL": {"price": 150.0},
"GOOG": {"price": 2500.0}
}
return stock_data.get(ticker, {"price": "未知"})
# 定义LLM类
class LLM:
def __init__(self):
self.functions = {
"获取当前天气": 获取当前天气,
"获取股票价格": 获取股票价格
}
def 调用函数(self, function_name, *args):
if function_name in self.functions:
return self.functions[function_name](*args)
else:
return {"error": "函数不存在"}
# 创建一个LLM实例
llm = LLM()
# 错误处理
print(llm.call_function("get_current_weather", "New York, NY"))
print(llm.call_function("get_stock_price", "AAPL"))
print(llm.call_function("get_weather_forecast", "New York, NY"))
{'天气': '晴', '气温': 75}
{'价钱': 150.0}
{'错误': '函数未定义'}
import json
from mistral import Mistral
# 定义自定义函数
def get_current_weather(location):
# 模拟获取当前天气的 API 调用
天气数据 = {
"New York, NY": {"weather": "晴朗", "temperature": 75},
"Los Angeles, CA": {"weather": "多云", "temperature": 65}
}
return 天气数据.get(location, {"weather": "未知", "temperature": "未知"})
def get_stock_price(ticker):
# 模拟获取股票价格的 API 调用
股票数据 = {
"AAPL": {"price": 150.0},
"GOOG": {"price": 2500.0}
}
return 股票数据.get(ticker, {"price": "未知"})
# 创建 Mistral 模型实例
mistral = Mistral("mistral-7b")
# 定义可用函数
函数 = {
"get_current_weather": get_current_weather,
"get_stock_price": get_stock_price
}
# 定义函数模式
函数模式 = {
"get_current_weather": {"parameters": {"location": {"type": "string"}}},
"get_stock_price": {"parameters": {"ticker": {"type": "string"}}}
}
# 测试函数调用
提示 = "纽约,纽约当前的天气如何?"
响应 = mistral.generate(提示, 函数模式)
如果 "function" 在 响应中:
function_name = 响应["function"]
function_args = 响应["arguments"]
如果 function_name 在 函数中:
结果 = 函数[function_name](function_args)
print(f"调用函数 {function_name},参数为 {function_args},结果为 {结果}")
否则:
打印(f"未找到函数 {function_name}")
否则:
打印("无需调用函数")
这段代码定义了两个自定义函数 get_current_weather
和 get_stock_price
,它们模拟 API 调用来获取天气数据和股票价格。然后,它创建了 Mistral 7B 模型的一个实例,并定义了可用函数及其模式定义。最后,通过生成对用户提示的响应并根据需要调用相应的函数来测试函数调用。
当你运行这段代码时,它会显示:
调用 get_current_weather 函数并传入参数 {'location': '纽约, NY'} 时结果为:{'天气': '晴', '温度': 75 华氏度}
从transformers import AutoTokenizer,AutoModelForCausalLM
import torch
model_id = "hiieu/Meta-Llama-3-8B-Instruct-function-calling-json-mode"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,torch_dtype = torch.bfloat16,
device_map="auto"
)
device = "cuda" if torch.cuda.is_available() else "cpu"
messages = [
{"role":"system","content":"你是一个乐于助人的助手,回答时请使用带有键\"messages\"的JSON格式"},
{"role": "user","content": "你是谁?"},
]
input_ids = tokenizer.apply_chat_template(
messages,
add_generate_prompt = True,
return_tensors = "pt"
).to(model.device)
terminators = [tokenizer.eos_token_id,
tokenizer.convert_tokens_to_ids("<|eot_id|>")]
output = model.generate(
input_ids,
max_new_tokens = 256,
eos_token_id = terminators,
do_sample = True,
temperature = 0.6,
top_p = 0.9,
top_k = 50,
repetition_penalty = 1.1,
pad_token_id = tokenizer.eos_token_id,
return_dict_in_generate = True,
)
functions_metadata= [
{
"type":"function",
"function":{
"name": "get_temperature",
"description" : "获取某城市当前的温度",
"parameters" : {
"type" : "object" ,
"properties" : {
"city" : {
"type" : "string",
"description" : "城市名"
}
},
"required" : ["city"]
}
}
}
]
messages = [{
"role": "system",
"content": f"""你是一个乐于助人的助手,可以访问以下功能:
{str(functions_metadata)}
使用这些功能时,请按照以下格式回复:
<functioncall> {{"name":"功能名称","arguments":{{"参数1":"值1","参数2":"值2",...}}}} </functioncall>
如果没有匹配用户请求的功能,你将礼貌地告知用户。"""
},
{"role": "user", "content": "东京当前的温度是多少?"},
{"role": "assistant", "content": """<functioncall>{"name":"get_temperature","arguments":{"city":"东京"}}</functioncall>"""},
{"role": "user", "content": """<function_response> {"temperature":30} </function_response>"""}
]
input_ids = tokenizer.apply_chat_template(
messages,
add_generate_prompt = True ,
return_tensors = "pt"
).to(model.device)
terminators = [
tokenizer.eos_token_id,
tokenizer.convert_tokens_to_ids("<|eot_id|>")
]
outputs = model.generate(
input_ids,
max_new_tokens = 256,
eos_token_id = terminators,
do_sample = True,
temperature = 0.6,
top_p = 0.9,
)
response = outputs[0][input_ids.shape[-1]:]
print(tokenizer.decode(response,skip_special_tokens=True))
共同學習,寫下你的評論
評論加載中...
作者其他優質文章