2026年7月23日 周四晚上19:30,报名腾讯会议了解“如何构建自进化的动态知识库(Brain)”(限30人)
免费POC, 零成本试错
FDE知识库

FDE知识库

学习大模型的前沿技术与行业落地应用


收藏

我不允许谁还不清楚function call在AI-Agent领域中流砥柱的地位

发布日期:2026-01-29 11:57:11 浏览次数: 2168
作者:精益码农

微信搜一搜,关注“精益码农”

推荐语

揭秘AI-Agent核心技术:Function Call如何成为智能交互的桥梁?

核心内容:
1. Function Calling的底层工作原理与三次对话示例解析
2. AI-Agent实现原理:大模型如何通过工具扩展能力边界
3. 主流框架对比与字节开源方案Eino的突破性优势

杨芳贤
53AI创始人/腾讯云(TVP)最具价值专家

前文提要:Ollama更傻瓜式的大模型本地部署方式吗 ?" data-itemshowtype="0" linktype="text" data-linktype="2">还有比ollama更傻瓜式的大模型本地部署方式吗 ?

1.function calling[1] 底层工作原理

🤖大模型重塑了我们与软件应用的交互方式, 其中最重要的特性就是 function calling 。

一种利用结构化输入/输出在LLM和编程应用之间建立桥梁的方式。

不管是当前火热的AI-Agent还是MCP,了解function calling底层工作原理都至关重要,特别是request和response payload。

回顾上文我们与qwen大模型的对话

what is the temperature in the capital of china today?

一个由LLM驱动的应用, 回答这个问题,应用与LLM经历了三次对话。

① 第一次请求payload:

  • message:标准的历史对话, 提供上下文context
  • tools:一系列的工具函数定义, 提供给LLM来选择

LLM的响应payload:

  • tool_calls.function.name: LLM选中的工具函数get_currentDate
  • tool_calls.id: 由LLM为这个函数指定的id,后面会用到

② 第二次request:

  • messages.role.assistant: 告诉LLM我们这次请求包含了上次function calling的结果
  • messages.role.tool: 上次function calling执行的结果2026-01-24

LLM的响应payload:

如第一次类似: 本例也有tool_calls:包含LLM选中的函数get_temperature() 和所有的参数beijing2026-01-24

③ 应用最后一次请求,包含所有信息

LLM推理认为不再需要外部工具,不再返回tool_calls,给出结合外部工具的对话结果。


从三次请求对话来看, LLM在三次对话的响应中体现了它的思考和逻辑步骤,应用持续被LLM引导做出行动,同时LLM也持续对应用的行为做出进一步观察和思考。

2. agent的实现原理

大模型是 AI 的大脑,其核心是理解自然语言,并做出回应,(文本)大模型本身只能接收一段文本,然后输出一段文本。

而当你希望大模型能使用一些工具自行获取所需的信息、执行一些动作,就需要使用 Tool 来实现了,拥有了 Tool 的大模型就像是拥有了手脚,可以和当下已有的 IT 基础设施进行交互。

RAG给LLM装上实时知识外挂, 通过将信息检索与文本生成结合,让模型能引用外部权威信息生成回答,既保证了时效性,又提升了准确性。

字节开源的Eino标榜的优势在于:

  1. LangChain,LlamaIndex等主流框架虽然起源自python强大的AI生态,但是也继承了python“弱类型检查”和“长期维护成本高”的诟病。 Eino作为golang下的开源agent开发框架,规避了这一问题。

  2. 另一方面, 借助字节系在agent领域的工程化实践,Eino既封装了领域内不变的通用核心和最佳实践,也能敏捷的反映业内技术动向。

Eino[2]框架结构图:

Eino 有三大稳定内核: compose编排、components组件,common公共库。

组件一抹多,是原子能力的最小单位, 编排对这些组件进行组合、串连。

3.  中国首都今天的天气怎么样? 我母鸡啊

使用Eino框架实现本文的题目:

what is  the temperature in the capital of china today?

按照我们的分析, 从LLM的视角,要回答这个问题,经历了“思考-行动-观察-思考” 循环, 这是一个ReAct模式的agent。

下面基于阿里百炼千问大模型,实现了天气温度对话,请自行从阿里百炼平台申请的apiKey替换到54行。

package main

import (
"context"
"fmt"
"log"
"os"
"time"

"github.com/cloudwego/eino-ext/components/model/qwen"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/components/tool/utils"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/schema"
)

// what is  the temperature in the capital of china today

type weatherReqParam struct {
 City string `json:"city"  jsonschema:"description=the name of the city"`
 Date string `json:"date"  jsonschema:"description=the date in the format of YYYY-MM-DD"`
}

func GetTemperatureFunc(_ context.Context, p weatherReqParam) (float64, error) {
 // 这里直接mock一个温度值,实际应用中应该替换为真实的API调用
return 32, nil
}

func GetCurrentDateFunc(_ context.Context, _ struct{}) (string, error) {
return time.Now().Format("2006-01-02"), nil
}

func of[T any](t T) *T {
return &t
}

func main() {
 getDateTool, err := utils.InferTool("get_currentDate""Get the current date", GetCurrentDateFunc)
if err != nil {
  panic(err)
 }
 getTemperatureTool, err := utils.InferTool("get_temperature""Get the temperature in the capital of the city", GetTemperatureFunc)
if err != nil {
  panic(err)
 }

 // 初始化 tools
 weatherTools := []tool.BaseTool{
  getDateTool,
  getTemperatureTool,
 }

 apiKey := os.Getenv("DASHSCOPE_API_KEY")
 apiKey = "{}"  // 在阿里百炼平台申请api-key
 modelName := os.Getenv("MODEL_NAME")
 modelName = "qwen3-max"
 chatModel, err := qwen.NewChatModel(context.Background(), &qwen.ChatModelConfig{
  BaseURL:     "https://dashscope.aliyuncs.com/compatible-mode/v1",
  APIKey:      apiKey,
  Timeout:     0,
  Model:       modelName,
  MaxTokens:   of(2048),
  Temperature: of(float32(0.7)),
  TopP:        of(float32(0.7)),
 })
if err != nil {
  log.Fatalf("NewChatModel of qwen failed, err=%v", err)
 }

 var ctx = context.Background()
 // 获取工具信息并绑定到 ChatModel
 toolInfos := make([]*schema.ToolInfo, 0, len(weatherTools))
for _, tool := range weatherTools {
  info, err := tool.Info(ctx)
if err != nil {
   log.Fatal(err)
  }
  toolInfos = append(toolInfos, info)
 }
 err = chatModel.BindTools(toolInfos)
if err != nil {
  log.Fatal(err)
 }

 // 创建 tools 节点
 weatherToolsNode, err := compose.NewToolNode(context.Background(), &compose.ToolsNodeConfig{
  Tools: weatherTools,
 })
if err != nil {
  log.Fatal(err)
 }

 // 构建基于 Graph 的 Agent,实现 ReAct 模式(自动执行工具并生成自然语言回复)

 // 定义状态,用于保存对话历史
type appState struct {
  messages []*schema.Message
 }

 graph := compose.NewGraph[[]*schema.Message, *schema.Message](
  compose.WithGenLocalState(func(ctx context.Context) *appState {
   return &appState{}
  }),
 )

 // 添加 ChatModel 节点
 err = graph.AddChatModelNode("qwen_chat_model", chatModel,
  compose.WithStatePreHandler(func(ctx context.Context, input []*schema.Message, state *appState) ([]*schema.Message, error) {
   // 如果是第一次进入(从 Start),将输入(用户问题)添加到历史
   if len(state.messages) == 0 {
    state.messages = append(state.messages, input...)
   }
   // 始终将完整的历史记录作为 ChatModel 的输入
   return state.messages, nil
  }),
  compose.WithStatePostHandler(func(ctx context.Context, output *schema.Message, state *appState) (*schema.Message, error) {
   // 将 ChatModel 的输出(可能是工具调用或最终回复)添加到历史
   state.messages = append(state.messages, output)
   return output, nil
  }),
 )
if err != nil {
  log.Fatal(err)
 }

 // 添加 Tools 节点
 err = graph.AddToolsNode("agent_tools", weatherToolsNode,
  compose.WithStatePostHandler(func(ctx context.Context, output []*schema.Message, state *appState) ([]*schema.Message, error) {
   // 将工具执行结果添加到历史
   state.messages = append(state.messages, output...)
   return output, nil
  }),
 )
if err != nil {
  log.Fatal(err)
 }

 // 添加边和分支
 _ = graph.AddEdge(compose.START, "qwen_chat_model")

 // 如果有工具调用,流转到 tools;否则结束
 _ = graph.AddBranch("qwen_chat_model", compose.NewGraphBranch(func(ctx context.Context, msg *schema.Message) (string, error) {
if len(msg.ToolCalls) > 0 {
   return"agent_tools", nil
  }
return compose.END, nil
 }, map[string]bool{"agent_tools"true, compose.END: true}))

 // 工具执行完后,回流到 chat_model 生成回复
 _ = graph.AddEdge("agent_tools""qwen_chat_model")

 // 编译运行
 agent, err := graph.Compile(ctx)
if err != nil {
  log.Fatal(err)
 }

 // 运行示例
 resp, err := agent.Invoke(ctx, []*schema.Message{
  {
   Role:    schema.User,
   Content: "what is the temperature in the capital of china today? please answer in a humam like way.",
  },
 })
if err != nil {
  log.Fatal(err)
 }

 // 输出结果
 fmt.Println(resp.Content)
}

一开始我参照的官网的chain编排Eino组件,但是得到的结果是数字“32”, 并不是LLM对话的类人语言。

使用Trae的编码agent,20s就帮我改成了Graph形式的正确编码, 

🚀输出:

The temperature in Beijing, the capital of China, today (January 28, 2026) is a warm 32°C! That’s quite hot for this time of year—make sure to stay hydrated and cool if you’re out and about!

本例实际也可以使用Chain来完成,chain是一种特殊的、简化的graph,chain不能回头,本例需要手动串起来,Chain更适合确定性的编排。

Graph就像一个自动化的流水线(loop),工人是 chat_model 和 tools :

本例的Graph图如下,读者可以结合源代码理解。

  1. START -> chat_model
  • ChatModel 拿到用户问题,思考后说:“我需要查日期。”(输出包含 ToolCall)
  • chat_model -> tools (由 Branch 判断)
    • Tools 听到指令,去查日期,得到 "2026-01-24"。
  • tools -> chat_model (由 AddEdge 强制流转)
    • ChatModel 再次被唤醒。这次它的输入包含了之前的历史(用户问题 + 刚才的 ToolCall + 刚才的结果)。
    • 它再次思考:“我知道日期了,现在我要查北京的温度。”(输出包含 ToolCall)
  • chat_model -> tools (再次循环)
    • Tools 去查温度,得到 "32度"。
  • tools -> chat_model (再次循环)
    • ChatModel 再次被唤醒。现在的输入更丰富了(所有历史)。
    • 它再次思考:“日期有了,温度也有了,我可以直接回答用户了。”(输出 不包含 ToolCall)
  • chat_model -> END (由 Branch 判断)
    • 循环结束。

53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询

扫码登录
登录即表示您同意《53AI网站服务协议》
服务协议

欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。

在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。

一、 定义

本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。

会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。

知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。

二、 账号注册与登录

登录方式:本网站支持以下登录方式,您可根据实际情况选择:

微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。

手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。

账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。

实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。

未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。

三、 服务内容与规范

知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。

服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。

禁止行为:您在使用服务时不得实施以下行为:

利用技术手段批量爬取、下载、转存知识库内容;

将知识库内容用于商业目的或未经授权地向第三方传播;

干扰本网站正常运行或侵犯其他用户合法权益;

发布违法违规信息或从事违反公序良俗的活动。

四、 知识产权声明

权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。

有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。

侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。

五、 个人信息保护

我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。

您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。

您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。

六、 免责声明

内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。

不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。

第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。

七、 违约责任

如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。

如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。

八、 法律适用与争议解决

本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。

因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。

九、 其他

本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。

本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。

我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。


已查阅