- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
众所周知,LLM的函数function-calling能力很强悍,解决了大模型与实际业务系统的交互问题。其本质就是函数调用.
从openai官网摘图:
。
简而言之:LLM起到决策的作用,告知业务系统应该调用什么函数,以及入参是什么.
业务系统负责实现对应的函数(比如本地实现,或者调用其他系统提供的服务),并且将函数的响应结果再次抛给LLM.
在这里,有很多小伙伴会有一个误区:误以为函数调用是有LLM本身执行的。其实,LLM仅仅做决策,而实际的调用是由业务系统完成的.
现阶段,function-calling能力的实现有两种主流方式:LLM本身支持.
利用Prompt模板实现,典型如ReAct模板.
。
在实际的应用过程中,我们还要解决另一个重要问题:
function-calling触发机制是怎样的?也即:何时要使用function-calling能力,何时不应该使用?
这个问题的处理方式,对于整体流程的运行至关重要.
此时,我们可以使用特定Prompt来解决该问题:
You have access to the following tools:
{json.dumps(tools)}
You can select one of the above tools or just response user's content and respond with only a JSON object matching the following schema:
{{
"tool": <name of the selected tool>,
"tool_input": <parameters for the selected tool, matching the tool'
s JSON schema>,
"message": <direct response users content>}
该Prompt告知了LLM:如果需要使用function-calling能力,那么就从tools(tools是预定义的functions)中选取一个最匹配的函数;如果不需要,就用自然语言与用户交互,此时与正常的对话流程无异。输出的格式固定为json,方便解析.
由此,我们受到启发:只要LLM基座够强(能够严格遵循Prompt响应诉求),即使LLM本身不支持function-calling,我们也可以自己实现function-calling,脱离对特定LLM的依赖! 。
拿到function-calling的结果后,若要用自然语言的形式输出结果,还要再调用一次LLM,对结果进行整合。此时可以使用另一个Prompt:
Please generate a natural language description based on the following question and answer.
Question: [Content of the question]
Answer: [Content of the answer]
Generated Description: The result of [key phrase from the question] is [answer].
If necessary, you can polish the description.Only output the Description, with Chinese language.
该Prompt的作用就是告诉LLM,你要根据我的问题和答案,用自然语言重新描述一遍。这里指定了中文输出,可根据实际需要进行调整.
以下是一个可运行的完整Python脚本:
import requests
import json
import random
# 预置函数定义
tools = [
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city e.g. Beijing"
},
"unit": {
"type": "string",
"enum": [
"celsius"
]
}
},
"required": [
"location"
]
}
},
{
"name": "calculator",
"description": "计算器",
"parameters": {
"type": "int",
"properties": {
"a": {
"type": "int",
"description": "the first number"
},
"b": {
"type": "int",
"description": "the second number"
}
},
"required": [
"a",
"b"
]
}
}
]
# 获取天气(随机返回,实际使用可以替换为api调用)
def get_current_weather(*args):
# 定义可能的天气状态
weather_conditions = ["sunny", "cloudy", "rainy", "snowy"]
# 定义可能的温度范围
temperature_min = -10 # 最低温度,摄氏度
temperature_max = 35 # 最高温度,摄氏度
# 随机选择一个天气状态
condition = random.choice(weather_conditions)
# 随机生成一个温度
temperature = random.randint(temperature_min, temperature_max)
# 返回一个描述当前天气的字符串
return f"The weather of {args[0].get('location')} is {condition}, and the temperature is {temperature}°C."
def calculator(args):
return sum(value for value in args.values() if isinstance(value, int))
# 函数映射集合
functions = {
"get_current_weather": get_current_weather,
"calculator": calculator,
}
# 驱动整体流程的入口prompt
entrance_prompt = f"""You have access to the following tools:
{json.dumps(tools)}
You can select one of the above tools or just response user's content and respond with only a JSON object matching the following schema:
{{
"tool": <name of the selected tool>,
"tool_input": <parameters for the selected tool, matching the tool's JSON schema>,
"message": <direct response users content>
}}"""
# 请以自然语言的形式对结果进行描述
conformity_prompt = f"""
Please generate a natural language description based on the following question and answer.
Question: [Content of the question]
Answer: [Content of the answer]
Generated Description: The result of [key phrase from the question] is [answer].
If necessary, you can polish the description.
Only output the Description, with Chinese language.
"""
def extract_json(s):
stack = 0
start = s.find('{')
if start == -1:
return None
for i in range(start, len(s)):
if s[i] == '{':
stack += 1
elif s[i] == '}':
stack -= 1
if stack == 0:
return s[start:i + 1]
return None
# 结果包装器,type为func表示是函数调用返回的结果,default表示是自然语言结果。对于func返回的结果,会用LLM再次总结
class ResultWrapper:
def __init__(self, type, result):
self.type = type
self.result = result
# 解析LLM返回的结果,如果有json则去解析json
def parse_result(res):
json_str = extract_json(res["message"]["content"])
if json_str is not None:
obj = json.loads(json_str)
if "tool" in obj:
if obj["tool"] in functions:
fun = functions[obj["tool"]]
return ResultWrapper("func", fun(obj["tool_input"]))
else:
return ResultWrapper("default", obj["message"])
else:
return ResultWrapper("default", res["message"]["content"])
else:
return ResultWrapper("default", res["message"]["content"])
def invokeLLM(messages):
url = "${domain}/v1/chat/completions" #需替换域名
model = ""
payload = {
"model": model,
"messages": messages,
}
payload = json.dumps(payload)
headers = {
'Content-Type': 'application/json'
}
print("PAYLOAD: ", payload)
response = requests.request("POST", url, headers=headers, data=payload)
print("RESPONSE: ", response.text)
print("=======================================================================")
resp = json.loads(response.text)
return resp["choices"][0]
if __name__ == '__main__':
while True:
messages = [
{
"role": "system",
"content": entrance_prompt
}
]
user_input = input('Enter a string: ')
messages.append({
"role": "user",
"content": user_input
})
result_wrapper = parse_result(invokeLLM(messages))
if result_wrapper.type == "func":
messages = [
{
"role": "user",
"content": f"{conformity_prompt}\n\nThe question:{user_input}\nThe answer:{result_wrapper.result}"
}
]
print("FINAL RESULT WITH FUNCTION CALL: ", parse_result(invokeLLM(messages)).result)
else: print("FINAL RESULT: ", result_wrapper.result
实验效果:
Enter a string: 你好
PAYLOAD: {"model": "", "messages": [{"role": "system", "content": "You have access to the following tools:\n[{\"name\": \"get_current_weather\", \"description\": \"Get the current weather in a given location\", \"parameters\": {\"type\": \"object\", \"properties\": {\"location\": {\"type\": \"string\", \"description\": \"The city e.g. Beijing\"}, \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\"]}}, \"required\": [\"location\"]}}, {\"name\": \"calculator\", \"description\": \"\\u8ba1\\u7b97\\u5668\", \"parameters\": {\"type\": \"int\", \"properties\": {\"a\": {\"type\": \"int\", \"description\": \"the first number\"}, \"b\": {\"type\": \"int\", \"description\": \"the second number\"}}, \"required\": [\"a\", \"b\"]}}]\nYou can select one of the above tools or just response user's content and respond with only a JSON object matching the following schema:\n{\n \"tool\": <name of the selected tool>,\n \"tool_input\": <parameters for the selected tool, matching the tool's JSON schema>,\n \"message\": <direct response users content>\n}"}, {"role": "user", "content": "\u4f60\u597d"}]}
RESPONSE: {"model":"","object":"","choices":[{"index":0,"message":{"role":"assistant","content":"```json\n{\"tool\": null, \"tool_input\": null, \"message\": \"你好,有什么可以帮您的吗?\"}\n```","function_call":null},"finish_reason":"stop"}],"queueTime":0.0020923614501953125,"costTime":0.7685532569885254,"usage":{"prompt_token":244,"completion_token":29,"total_tokens":273}}
=======================================================================
FINAL RESULT: 你好,有什么可以帮您的吗?
Enter a string: 厦门天气如何?
PAYLOAD: {"model": "", "messages": [{"role": "system", "content": "You have access to the following tools:\n[{\"name\": \"get_current_weather\", \"description\": \"Get the current weather in a given location\", \"parameters\": {\"type\": \"object\", \"properties\": {\"location\": {\"type\": \"string\", \"description\": \"The city e.g. Beijing\"}, \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\"]}}, \"required\": [\"location\"]}}, {\"name\": \"calculator\", \"description\": \"\\u8ba1\\u7b97\\u5668\", \"parameters\": {\"type\": \"int\", \"properties\": {\"a\": {\"type\": \"int\", \"description\": \"the first number\"}, \"b\": {\"type\": \"int\", \"description\": \"the second number\"}}, \"required\": [\"a\", \"b\"]}}]\nYou can select one of the above tools or just response user's content and respond with only a JSON object matching the following schema:\n{\n \"tool\": <name of the selected tool>,\n \"tool_input\": <parameters for the selected tool, matching the tool's JSON schema>,\n \"message\": <direct response users content>\n}"}, {"role": "user", "content": "\u53a6\u95e8\u5929\u6c14\u5982\u4f55\uff1f"}]}
RESPONSE: {"model":"","object":"","choices":[{"index":0,"message":{"role":"assistant","content":"```json\n{\"tool\": \"get_current_weather\", \"tool_input\": {\"location\": \"Xiamen\", \"unit\": \"celsius\"}, \"message\": \"\"}\n```","function_call":null},"finish_reason":"stop"}],"queueTime":0.0021338462829589844,"costTime":0.9370713233947754,"usage":{"prompt_token":247,"completion_token":36,"total_tokens":283}}
=======================================================================
PAYLOAD: {"model": "", "messages": [{"role": "user", "content": "\nPlease generate a natural language description based on the following question and answer.\nQuestion: [Content of the question]\nAnswer: [Content of the answer]\nGenerated Description: The result of [key phrase from the question] is [answer].\nIf necessary, you can polish the description.\nOnly output the Description, with Chinese language.\n\n\nThe question:\u53a6\u95e8\u5929\u6c14\u5982\u4f55\uff1f\nThe answer:The weather of Xiamen is cloudy, and the temperature is 35\u00b0C."}]}
RESPONSE: {"model":"","object":"","choices":[{"index":0,"message":{"role":"assistant","content":"厦门天气情况是:多云,气温35°C。","function_call":null},"finish_reason":"stop"}],"queueTime":0.008246660232543945,"costTime":0.3240656852722168,"usage":{"prompt_token":143,"completion_token":12,"total_tokens":155}}
=======================================================================
FINAL RESULT WITH FUNCTION CALL: 厦门天气情况是:多云,气温35°C。
Enter a string: 383加上135721等于多少?
PAYLOAD: {"model": "", "messages": [{"role": "system", "content": "You have access to the following tools:\n[{\"name\": \"get_current_weather\", \"description\": \"Get the current weather in a given location\", \"parameters\": {\"type\": \"object\", \"properties\": {\"location\": {\"type\": \"string\", \"description\": \"The city e.g. Beijing\"}, \"unit\": {\"type\": \"string\", \"enum\": [\"celsius\"]}}, \"required\": [\"location\"]}}, {\"name\": \"calculator\", \"description\": \"\\u8ba1\\u7b97\\u5668\", \"parameters\": {\"type\": \"int\", \"properties\": {\"a\": {\"type\": \"int\", \"description\": \"the first number\"}, \"b\": {\"type\": \"int\", \"description\": \"the second number\"}}, \"required\": [\"a\", \"b\"]}}]\nYou can select one of the above tools or just response user's content and respond with only a JSON object matching the following schema:\n{\n \"tool\": <name of the selected tool>,\n \"tool_input\": <parameters for the selected tool, matching the tool's JSON schema>,\n \"message\": <direct response users content>\n}"}, {"role": "user", "content": "383\u52a0\u4e0a135721\u7b49\u4e8e\u591a\u5c11\uff1f"}]}
RESPONSE: {"model":"","object":"","choices":[{"index":0,"message":{"role":"assistant","content":"```json\n{\"tool\": \"calculator\", \"tool_input\": {\"a\": 383, \"b\": 135721}, \"message\": null}\n```","function_call":null},"finish_reason":"stop"}],"queueTime":0.0021514892578125,"costTime":0.9161381721496582,"usage":{"prompt_token":252,"completion_token":35,"total_tokens":287}}
=======================================================================
PAYLOAD: {"model": "", "messages": [{"role": "user", "content": "\nPlease generate a natural language description based on the following question and answer.\nQuestion: [Content of the question]\nAnswer: [Content of the answer]\nGenerated Description: The result of [key phrase from the question] is [answer].\nIf necessary, you can polish the description.\nOnly output the Description, with Chinese language.\n\n\nThe question:383\u52a0\u4e0a135721\u7b49\u4e8e\u591a\u5c11\uff1f\nThe answer:136104"}]}
RESPONSE: {"model":"","object":"","choices":[{"index":0,"message":{"role":"assistant","content":"383加上135721等于136104。","function_call":null},"finish_reason":"stop"}],"queueTime":0.0064160823822021484,"costTime":0.28981900215148926,"usage":{"prompt_token":134,"completion_token":11,"total_tokens":145}}
=======================================================================
FINAL RESULT WITH FUNCTION CALL: 383加上135721等于136104。
在这个例子中,预置了两个函数,分别为天气查询和计算器,实验效果中进行了三轮,其中第一次属于未命中函数调用的闲聊场景,后两次分别命中了天气查询和计算器.
在实际的工作中,可能需要预置非常多函数能力,此时可能需要考虑到LLM的输入token限制,必要时需要进行模块划分,将一次LLM决策转化为多次决策,更通用一点的说法就是意图层级识别.
最后此篇关于如何实现LLM的通用function-calling能力?的文章就讲到这里了,如果你想了解更多关于如何实现LLM的通用function-calling能力?的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
main.cpp #include "Primes.h" #include int main(){ std::string choose; int num1, num2; w
似乎函数 qwertyInches() 应该可以工作但是当我在 main() 中调用它时它给了我 [Error] called object 'qwertyInches' is not a funct
我无法理解 C++ 语法的工作原理。 #include using namespace std; class Accumulator{ private: int value; public:
在 类中声明 函数成员时,我们可以同时执行这两种操作; Function first; Function() second; 它们之间有什么区别? 最佳答案 Function 代表任意函数: void
“colonna”怎么可能是一个简单的字符串: $('td.' + colonna).css('background-color','#ffddaa'); 可以正确突出显示有趣单元格的背景,并且: $
我正在尝试将网页中的动态参数中继到函数中,然后函数将它们传递给函数内部的调用。比如下面这个简化的代码片段,现在这样,直接传入参数是没有问题的。但是,如何在不为每个可能的 colorbox 参数设置 s
C++ 中是否有一种模式允许您返回一个函数,它返回一个函数本身。例如 std::function func = ...; do { func = func(); } while (func);
我正在将 Windows 程序集移植到 Linux。我有一些代码要移植。我实际上是 linux 中 C 的新手。我知道 C 基础知识是一样的! typedef struct sReader {
我一直在寻找一个很好的解释,所以我很清楚。示例: this.onDeleteHandler(index)}/> 对比 对比 this.nameChangedhandler(event, perso
function(){}.__proto__ === Function.prototype 和 Function.prototype === function(){}.__proto__ 得到不同的结
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function 据说 Propert
VBA 中的函数没有特殊类型。我很难理解如何在 Excel VBA 中将函数作为参数添加到函数中。 我想要完成的是这样的事情: function f(g as function, x as strin
所以我正在尝试制作一个包(我没有在下面包含我的 roxygen2 header ): 我有这个功能: date_from_text % dplyr::mutate(!!name := lubr
尝试从 std::function 派生一个类,对于初学者来说,继承构造函数。这是我的猜测: #include #include using namespace std; template cla
我正在尝试编写一个返回另一个函数的函数。我的目标是编写一个函数,它接受一个对象并返回另一个函数“search”。当我使用键调用搜索函数时,我想从第一个函数中给定的对象返回该键的值。 propertyO
我非常清楚函数式编程技术和命令式编程技术之间的区别。但是现在有一种普遍的趋势是谈论“函数式语言”,这确实让我感到困惑。 当然,像 Haskell 这样的一些语言比 C 等其他语言更欢迎函数式编程。但即
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 8 年前。 Improv
我在stackoverflow上查过很多类似的问题,比如call.call 1 , call.call 2 ,但我是新人,无法发表任何评论。我希望我能找到关于 JavaScript 解释器如何执行这些
向 Twilio 发送 SMS 时,Twilio 会向指定的 URL 发送多个请求,以通过 Webhook 提供该 SMS 传送的状态。我想让这个回调异步,所以我开发了一个 Cloud Functio
作为 IaC 的一部分,A 功能应用 ,让我们将其命名为 FuncAppX 是使用 Terraform 部署的,它有一个内置函数。 我需要使用 Terraform 在函数应用程序中访问相同函数的 Ur
我是一名优秀的程序员,十分优秀!