模型Function Call

工具调用(Function Calling)是一种将大模型与外部工具和 API 相连的关键功能,作为自然语言与信息接口之间的“翻译官”,它能够将用户的自然语言请求智能地转化为对特定工具或 API 的调用,从而高效满足用户的特定需求。

简单来说,大模型的知识是固定的,你问他李白有哪些诗它肯定知道,但是你问它现在北京天气怎么样,它就不知道了。但大模型有推理能力,如果你问它北京天气怎么样的同时,还告诉他有哪些API可以使用,它就会选择对应的API。这样我们可以用工程手段调用这些API,然后将API结果再给大模型,由大模型进行总结了。

前置操作

首先我们得开通个大模型,这里我用火山的模型来演示。吐槽一句,我感觉各家的云平台操作起来都听不顺畅的,找个内容得四处翻。

登录:https://www.volcengine.com/

进入控制台:https://console.volcengine.com/ark/region:ark+cn-beijing/overview?briefPage=0&briefType=introduce&projectName=undefined&type=new

开通模型:我选择开通的是豆包-1.5-pro-32k

在这里插入图片描述

查看模型细节:

在这里插入图片描述

获取API key和使用demo,大家shell里执行export ARK_API_KEY="**"就能执行我下面的代码了

在这里插入图片描述

代码

看代码前,希望大家能先看一下这两个文档

  1. Chat接口的入参和出参:https://www.volcengine.com/docs/82379/1494384?redirect=1
  2. Function Call的调用方式:https://www.volcengine.com/docs/82379/1262342 ,这个文档主要使用的是非流式方式,而且Go的demo很少,强烈建议加个流式的demo
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"os"

	"github.com/volcengine/volcengine-go-sdk/service/arkruntime"
	"github.com/volcengine/volcengine-go-sdk/service/arkruntime/model"
	"github.com/volcengine/volcengine-go-sdk/volcengine"
)

type WeatherArgs struct {
	Location string `json:"location"`
	Unit     string `json:"unit,omitempty"` // omitempty 允许 unit 为可选
}

// 目标工具
func getCurrentWeather(location string, unit string) string {
	if unit == "" {
		unit = "摄氏度" // 默认单位
	}
	// 此处为示例,返回模拟的天气数据
	return fmt.Sprintf("%s今天天气晴朗,温度 25 %s。", location, unit)
}

func MarshStr(data interface{}) string {
	d, _ := json.Marshal(data)
	return string(d)
}

func main() {
	// 从环境变量中获取 API Key,请确保已设置 ARK_API_KEY
	apiKey := os.Getenv("ARK_API_KEY")
	if apiKey == "" {
		fmt.Println("错误:请设置 ARK_API_KEY 环境变量。")
		return
	}

	client := arkruntime.NewClientWithApiKey(apiKey)
	ctx := context.Background()

	// 初始化消息列表
	messages := []*model.ChatCompletionMessage{
		{
			Role: model.ChatMessageRoleSystem,
			Content: &model.ChatCompletionMessageContent{
				StringValue: volcengine.String("你是豆包,是由字节跳动开发的 AI 人工智能助手"),
			},
		},
		{
			Role: model.ChatMessageRoleUser,
			Content: &model.ChatCompletionMessageContent{
				StringValue: volcengine.String("先帮我查看一下北京的天气,然后再查看一下上海的天气"),
			},
		},
	}

	// 步骤 1: 定义工具
	tools := []*model.Tool{
		{
			Type: model.ToolTypeFunction,
			Function: &model.FunctionDefinition{
				Name:        "get_current_weather",
				Description: "获取指定地点的天气信息",
				Parameters: map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"location": map[string]interface{}{
							"type":        "string",
							"description": "地点的位置信息,例如北京、上海",
						},
						"unit": map[string]interface{}{
							"type": "string",
							"enum": []string{
								"摄氏度",
								"华氏度",
							},
							"description": "温度单位",
						},
					},
					"required": []string{"location"},
				},
			},
		},
	}
	count := 0
	for {
		if count > 5 {
			return
		}
		count++
		// 步骤 2: 发起流式模型请求
		req := model.CreateChatCompletionRequest{
			Model:    "doubao-1-5-pro-32k-250115",
			Messages: messages,
			Tools:    tools,
			Stream:   volcengine.Bool(true),
		}

		fmt.Println("----- streaming request -----")
		stream, err := client.CreateChatCompletionStream(ctx, req)
		//fmt.Print(2)
		if err != nil {
			fmt.Printf("stream chat error: %v\n", err)
			return
		}
		defer stream.Close()
		content := ""
		toolName := ""
		toolArgs := ""
		toolCallId := ""
		//fmt.Print(11)
		for {
			recv, err := stream.Recv()
			if err == io.EOF {
				break
			}
			if err != nil {
				fmt.Printf("Stream chat error: %v\n", err)
				return
			}

			if len(recv.Choices) > 0 {
				respMsg := recv.Choices[0].Delta
				// data, _ := json.Marshal(recv.Choices[0])
				// fmt.Println(string(data))

				// fmt.Print("content: "+recv.Choices[0].Delta.Content, "finishreason: "+recv.Choices[0].FinishReason, "\n")

				//fmt.Println(recv.Choices[0].Delta.ToolCalls[0], recv.Choices[0].Delta.Content)
				//展示模型中间过程的回复内容
				if respMsg.Content != "" {
					content += respMsg.Content
					fmt.Print(respMsg.Content)
				}

				//处理工具信息
				if len(recv.Choices[0].Delta.ToolCalls) > 0 {
					toolCall := recv.Choices[0].Delta.ToolCalls[0]
					if toolCall.Function.Name != "" {
						toolName = toolCall.Function.Name
					}
					if toolCall.Function.Arguments != "" {
						toolArgs += toolCall.Function.Arguments
					}
					if toolCall.ID != "" {
						toolCallId = toolCall.ID
					}
				}
				//处理非fc的结束
				if recv.Choices[0].FinishReason != "" && recv.Choices[0].FinishReason != model.FinishReasonToolCalls {
					messages = append(messages, &model.ChatCompletionMessage{
						Role: model.ChatMessageRoleAssistant,
						Content: &model.ChatCompletionMessageContent{
							StringValue: volcengine.String(content),
						},
					},
					)
					fmt.Println("正常finish", MarshStr(messages))
					return //真正结束
				}
				//处理fc的结束
				if recv.Choices[0].FinishReason == model.FinishReasonToolCalls && len(toolName) > 0 {
					// 将模型的回复(包含工具调用请求)添加到消息历史中
					messages = append(messages, &model.ChatCompletionMessage{
						Role: model.ChatMessageRoleAssistant,
						Content: &model.ChatCompletionMessageContent{
							StringValue: volcengine.String(content),
						},
						ToolCalls: []*model.ToolCall{
							{
								ID: toolCallId,
								Function: model.FunctionCall{
									Name:      toolName,
									Arguments: toolArgs,
								},
								Type: model.ToolTypeFunction,
							},
						},
					})

					fmt.Printf("\n模型尝试调用工具: %s, ID: %s", toolName, toolCallId)
					fmt.Println("  参数:", toolArgs)

					var toolResult string
					if toolName == "get_current_weather" {
						// 调用外部工具
						var args WeatherArgs
						err := json.Unmarshal([]byte(toolArgs), &args)
						if err != nil {
							fmt.Printf("解析工具参数错误 (%s): %v", toolName, err)
							toolResult = fmt.Sprintf("解析参数失败: %v", err)
						} else {
							toolResult = getCurrentWeather(args.Location, args.Unit)
							fmt.Println("  工具执行结果:", toolResult)
						}

						// 回填工具结果
						messages = append(messages, &model.ChatCompletionMessage{
							Role:       model.ChatMessageRoleTool,
							Content:    &model.ChatCompletionMessageContent{StringValue: volcengine.String(toolResult)},
							ToolCallID: toolCallId,
							Name:       &toolName,
						})
					}

					fmt.Println("\n--- 下一轮对话 ---", MarshStr(messages))
					break
				}
			}
		}
		//break
	}
}

执行结果如下:

➜  my go run main.go
----- streaming request -----
用户需要查询北京和上海的天气,调用 get_current_weather 函数分别获取两地的天气信息。
模型尝试调用工具: get_current_weather, ID: call_pjov7bifbrdpv7e8kncsmhjz  参数:  {
        "location": "北京",
        "unit": "摄氏度"
    }
  工具执行结果: 北京今天天气晴朗,温度 25 摄氏度。

--- 下一轮对话 --- [{"role":"system","content":"你是豆包,是由字节跳动开发的 AI 人工智能助手","name":null},{"role":"user","content":"先帮我查看一下北京的天气,然后再查看一下上海的天气","name":null},{"role":"assistant","content":"用户需要查询北京和上海的天气,调用 get_current_weather 函数分别获取两地的天气信息。","name":null,"tool_calls":[{"id":"call_pjov7bifbrdpv7e8kncsmhjz","type":"function","function":{"name":"get_current_weather","arguments":" {\n        \"location\": \"北京\",\n        \"unit\": \"摄氏度\"\n    }"}}]},{"role":"tool","content":"北京今天天气晴朗,温度 25 摄氏度。","name":"get_current_weather","tool_call_id":"call_pjov7bifbrdpv7e8kncsmhjz"}]
----- streaming request -----

模型尝试调用工具: get_current_weather, ID: call_0qfxc8xe5h6m74pf9olwptao  参数:  {"location": "上海", "unit": "摄氏度"}
  工具执行结果: 上海今天天气晴朗,温度 25 摄氏度。

--- 下一轮对话 --- [{"role":"system","content":"你是豆包,是由字节跳动开发的 AI 人工智能助手","name":null},{"role":"user","content":"先帮我查看一下北京的天气,然后再查看一下上海的天气","name":null},{"role":"assistant","content":"用户需要查询北京和上海的天气,调用 get_current_weather 函数分别获取两地的天气信息。","name":null,"tool_calls":[{"id":"call_pjov7bifbrdpv7e8kncsmhjz","type":"function","function":{"name":"get_current_weather","arguments":" {\n        \"location\": \"北京\",\n        \"unit\": \"摄氏度\"\n    }"}}]},{"role":"tool","content":"北京今天天气晴朗,温度 25 摄氏度。","name":"get_current_weather","tool_call_id":"call_pjov7bifbrdpv7e8kncsmhjz"},{"role":"assistant","content":"","name":null,"tool_calls":[{"id":"call_0qfxc8xe5h6m74pf9olwptao","type":"function","function":{"name":"get_current_weather","arguments":" {\"location\": \"上海\", \"unit\": \"摄氏度\"}"}}]},{"role":"tool","content":"上海今天天气晴朗,温度 25 摄氏度。","name":"get_current_weather","tool_call_id":"call_0qfxc8xe5h6m74pf9olwptao"}]
----- streaming request -----
北京今天天气晴朗,温度 25 摄氏度。上海今天天气晴朗,温度 25 摄氏度。 正常finish [{"role":"system","content":"你是豆包,是由字节跳动开发的 AI 人工智能助手","name":null},{"role":"user","content":"先帮我查看一下北京的天气,然后再查看一下上海的天气","name":null},{"role":"assistant","content":"用户需要查询北京和上海的天气,调用 get_current_weather 函数分别获取两地的天气信息。","name":null,"tool_calls":[{"id":"call_pjov7bifbrdpv7e8kncsmhjz","type":"function","function":{"name":"get_current_weather","arguments":" {\n        \"location\": \"北京\",\n        \"unit\": \"摄氏度\"\n    }"}}]},{"role":"tool","content":"北京今天天气晴朗,温度 25 摄氏度。","name":"get_current_weather","tool_call_id":"call_pjov7bifbrdpv7e8kncsmhjz"},{"role":"assistant","content":"","name":null,"tool_calls":[{"id":"call_0qfxc8xe5h6m74pf9olwptao","type":"function","function":{"name":"get_current_weather","arguments":" {\"location\": \"上海\", \"unit\": \"摄氏度\"}"}}]},{"role":"tool","content":"上海今天天气晴朗,温度 25 摄氏度。","name":"get_current_weather","tool_call_id":"call_0qfxc8xe5h6m74pf9olwptao"},{"role":"assistant","content":"北京今天天气晴朗,温度 25 摄氏度。上海今天天气晴朗,温度 25 摄氏度。 ","name":null}]

我的问题是:先帮我查看一下北京的天气,然后再查看一下上海的天气。

我同时告诉模型,有获取天气的API-get_current_weather可以调用。

第一次:信息给到模型后,模型认为需要分别获取两地的天气,所以先返回了查询北京的参数,并决定调用get_current_weather进行查询。

{
“location”: “北京”,
“unit”: “摄氏度”
}

我代码里收到是调用工具,开始调用API,并将结果添加到msg中。

第二次:带着上次的信息给模型后,模型推理要查上海的天气了,同理我完成了一次API调用

第三次:带着两个地区的天气信息我给模型,模型认为无需调用工具,正常结束,这次会话就完全完成了。

我们看一下最终的消息体:

[
    {
        "role": "system",
        "content": "你是豆包,是由字节跳动开发的 AI 人工智能助手",
        "name": null
    },
    {
        "role": "user",
        "content": "先帮我查看一下北京的天气,然后再查看一下上海的天气",
        "name": null
    },
    {
        "role": "assistant",
        "content": "用户需要查询北京和上海的天气,调用 get_current_weather 函数分别获取两地的天气信息。",
        "name": null,
        "tool_calls": [
            {
                "id": "call_pjov7bifbrdpv7e8kncsmhjz",
                "type": "function",
                "function": {
                    "name": "get_current_weather",
                    "arguments": " {\n        \"location\": \"北京\",\n        \"unit\": \"摄氏度\"\n    }"
                }
            }
        ]
    },
    {
        "role": "tool",
        "content": "北京今天天气晴朗,温度 25 摄氏度。",
        "name": "get_current_weather",
        "tool_call_id": "call_pjov7bifbrdpv7e8kncsmhjz"
    },
    {
        "role": "assistant",
        "content": "",
        "name": null,
        "tool_calls": [
            {
                "id": "call_0qfxc8xe5h6m74pf9olwptao",
                "type": "function",
                "function": {
                    "name": "get_current_weather",
                    "arguments": " {\"location\": \"上海\", \"unit\": \"摄氏度\"}"
                }
            }
        ]
    },
    {
        "role": "tool",
        "content": "上海今天天气晴朗,温度 25 摄氏度。",
        "name": "get_current_weather",
        "tool_call_id": "call_0qfxc8xe5h6m74pf9olwptao"
    },
    {
        "role": "assistant",
        "content": "北京今天天气晴朗,温度 25 摄氏度。上海今天天气晴朗,温度 25 摄氏度。 ",
        "name": null
    }
]

FC在我眼里就像是人的四肢,模型是大脑,只有这样才能发挥更大的作用。如果加上硬件,那就是配备了钛合金盔甲。

疑问

流式调用是为了能够尽快将模型返回内容返回给前端,如果是最终结果肯定没什么问题,但是如果是fc的呢?有办法即使用流式方案,同时只把tool相关的内容返回,content的内容不返回吗?

➜  my go run main.go
----- streaming request -----
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"用户","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"想","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"了解","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"北京","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"和","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"上海","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"的","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"天气","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":",","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"调用","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":" get","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"_current","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"_","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"weather","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":" ","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"函数","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"获取","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"北京","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"和","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"上海","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"的","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"天气","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"信息","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"content":"。","role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"call_d17ewqycgbxdfj65zqycj3bu","type":"function","function":{"name":"get_current_weather"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":" {"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"\n"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"       "},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":" \""},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"location"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"\":"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":" \""},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"北京"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":","},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"上海"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"\","},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"\n"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"       "},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":" \""},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"unit"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"\":"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":" \""},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"摄氏度"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"\""},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"\n"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":"   "},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{"arguments":" }"},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant","tool_calls":[{"id":"","type":"","function":{},"index":0}]},"finish_reason":null}
{"index":0,"delta":{"role":"assistant"},"finish_reason":"tool_calls"}

资料

https://www.volcengine.com/docs/82379/1494384?redirect=1

https://www.volcengine.com/docs/82379/1262342#%E6%B5%81%E5%BC%8F%E8%BE%93%E5%87%BA%E9%80%82%E9%85%8D

https://www.volcengine.com/docs/82379/1449722

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

往期文章回顾:

  1. 设计模式

  2. 招聘

  3. 思考

  4. 存储

  5. 算法系列

  6. 读书笔记

  7. 小工具

  8. 架构

  9. 网络

  10. Go语言

<think>嗯,用户现在问的是“大模型 function call”,也就是大模型如何调用函数。首先我需要理解“大模型”在这里指的是像GPT-4、PaLM这类大型语言模型Function call可能指的是让这些模型在生成文本的过程中调用外部函数或工具,以完成更复杂的任务,比如获取实时数据、进行计算或者访问数据库等。 接下来,我要回顾之前的对话历史。用户之前询问过DeepSeek Prompt,是关于如何优化提示工程来提升模型输出的。现在这个问题可能是在探索如何让大模型不仅仅是生成文本,还能与外部系统交互,执行具体功能。这可能涉及到模型的功能扩展和应用场景的拓展。 需要确定用户的具体需求。他们可能想知道大模型如何调用函数,比如在开发聊天机器人时,让模型在回答用户问题时调用天气API获取实时数据。或者,他们可能对实现这种调用的技术细节感兴趣,比如API设计、模型训练方法等。 接下来,我应该分几个部分来介绍:首先定义什么是大模型function call,然后说明其工作原理,应用场景,常用方法,挑战与解决方案,最后结合实际例子,比如OpenAIFunction Calling功能,或者DeepSeek的可能实现方式。 需要注意的是,用户可能对技术细节有一定了解,但需要更系统的解释。因此,解释时需要平衡技术术语和通俗语言,确保不同背景的读者都能理解。同时,要避免过于冗长,但又要覆盖关键点,比如模型如何决定何时调用函数、如何传递参数、如何处理返回结果等。 另外,用户可能关心实际应用中的问题,比如安全性、效率、错误处理等,这些也应该在回答中提到。例如,模型调用外部API时的权限管理,错误回退机制,以及如何保证调用的准确性和可靠性。 最后,检查是否有遗漏的重要点,比如现有的框架或工具支持,如LangChain等库如何处理function call,或者企业级解决方案中的最佳实践。确保回答全面且结构清晰,帮助用户全面理解大模型function call的概念和应用。</think>以下是关于**大模型 Function Call(函数调用)**的详细介绍: --- ### **1. 核心概念** **大模型 Function Call** 指大型语言模型(如GPT-4、PaLM等)通过调用外部函数或工具,完成文本生成之外的复杂任务(如计算、数据查询、API交互等)。其本质是让模型具备**“决策+调用”**能力,即: - **理解用户需求** → **决定是否需要调用函数** → **生成调用参数** → **整合外部结果生成最终回复**。 --- ### **2. 工作原理** 1. **任务识别**:模型分析用户输入,判断是否需要调用函数(例如“北京天气如何?”需调用天气API)。 2. **参数生成**:模型根据需求生成函数调用所需的参数(如时间、地点、格式等)。 3. **执行函数**:系统调用外部工具或API,获取结果(如实时天气数据)。 4. **结果整合**:模型将外部结果与自身生成内容结合,输出最终回答。 --- ### **3. 典型应用场景** - **实时数据查询**:调用天气、股票、新闻等API。 - **复杂计算**:使用计算器、数据库或专业工具(如数学求解器)。 - **多模态扩展**:生成图像时调用文生图模型(如DALL·E),或处理语音时调用ASR(语音识别)。 - **自动化流程**:通过调用函数实现邮件发送、日程管理等功能。 --- ### **4. 实现方法** #### **a. 基于提示工程(Prompting)** - **显式指令**:要求模型返回函数调用格式(如JSON)。 ``` 用户:计算3的平方根。 系统:请以 { "function": "math_sqrt", "input": 3 } 格式返回调用需求。 ``` - **示例引导**:通过Few-Shot示例教会模型如何调用函数。 #### **b. 微调(Fine-tuning)** - 在训练数据中加入函数调用示例,让模型学习何时调用、如何传参。 - 例如:OpenAIFunction Calling功能通过微调模型识别调用需求。 #### **c. 框架支持** - **LangChain**:通过`Tools`模块将大模型与外部函数连接。 - **OpenAI Function Calling**:直接通过API定义函数,模型自动生成调用请求。 ```python # OpenAI示例:定义函数并调用 functions = [{ "name": "get_current_weather", "parameters": {"location": {"type": "string"}} }] response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[{"role": "user", "content": "北京天气如何?"}], functions=functions ) ``` --- ### **5. 技术挑战与解决方案** | **挑战** | **解决方案** | |-------------------------|-----------------------------------------------------------------------------| | 模型误判调用需求 | 设置置信度阈值,或提供备用回复逻辑(如“是否需要查询实时数据?”)。 | | 参数格式错误 | 后置校验逻辑(如JSON语法检查),或要求模型重新生成参数。 | | 外部工具响应延迟或失败 | 超时重试机制,或返回降级结果(如“暂时无法获取数据,以下是历史信息”)。 | | 安全风险(如敏感API调用)| 权限分级控制,仅允许白名单函数被调用。 | --- ### **6. 实例说明** **用户提问**: “帮我预订明天从北京到上海的高铁,下午出发。” **模型Function Call流程**: 1. **识别意图** → 调用“订票系统API”。 2. **生成参数** → `{出发地: "北京", 目的地: "上海", 日期: "2023-10-25", 时段: "下午"}`。 3. **API返回结果** → 获取车次列表(如G123、G456)。 4. **整合回复** → “找到以下车次:G123(14:00)、G456(15:30),是否需要预订?” --- ### **7. 与提示工程的关系** - **互补性**:Function Call依赖提示工程引导模型生成调用请求,同时扩展了模型能力边界。 - **差异**: - **提示工程**:优化模型自身的文本生成逻辑。 - **Function Call**:连接模型与外部工具,突破纯文本生成的局限。 --- ### **8. 企业级应用(如DeepSeek)** 若涉及特定厂商(如深度求索的DeepSeek-R1模型),其Function Call可能支持: - **私有化工具集成**:对接企业内部数据库或工具链。 - **领域定制化**:针对金融、医疗等场景预置专用函数库。 - **低代码配置**:通过可视化界面定义函数与调用规则。 --- 通过Function Call,大模型从“文本生成器”升级为“智能代理”,成为连接用户需求与现实世界的桥梁。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员麻辣烫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值