什么是Function Calling
2023年6月13日 OpenAI 公布了 Function Call(函数调用) 功能,该功能指的是在语言模型中集成外部功能或API的调用能力,这意味着模型可以在生成文本的过程中调用外部函数或服务,获取额外的数据或执行特定的任务
Function Call 应用基本流程(简化):

Function Call 功能
Function Call 可以解决大模型什么问题:
- 信息实时性:大模型训练的数据集无法包含最新的信息,如最新的新闻、实时股价等。通过Function Call,模型可以实时获取最新数据,提供更加时效的服务。
- 数据局限性:模型训练数据虽多但有限,无法覆盖所有领域,如医学、法律等领域的专业咨询,Function Call允许模型调用外部数据库或API,获取特定领域的详细信息。
- 功能扩展性:大模型虽然功能强大,但不可能内置所有可能需要的功能。通过Function Call,可以轻松扩展模型能力,如调用外部工具进行复杂计算、数据分析等。
Function Call 工作原理
Function Calling 并非指大语言模型LLM直接在自身沙盒内执行代码,而是一种结构化输出能力与协议。 它允许开发者向 LLM 声明一组本地或外部的函数签名,LLM 凭借其自然语言理解能力,自主判断是否需要调用这些函数来响应用户请求,并提取出符合规范的 JSON 参数包,交由宿主应用完成实际执行。
当没有函数调用(funciton-call)时候,我们调用GPT构建AI应用的模式非常简单。 主要步骤:
- 用户(Client)发请求给我们的服务(Chat Server)
- 我们的服务(Chat Server)给GPT提示词
- 重复执行

当有函数调用(funciton-call)时候,我们调用GPT构建AI应用的模式比之前要复杂一些。 主要步骤:
用户(Client)发请求prompt以及functions给我们的服务(Chat Server)
GPT模型根据用户的prompt,判断是用普通文本还是函数调用的格式响应我们的服务(Chat Server)
如果是函数调用格式,那么Chat Server就会执行这个函数,并且将结果返回给GPT
然后模型使用提供的数据,用连贯的文本响应。返回
注意:大模型的 Function call 不会调用函数,仅返回函数的参数。开发者利用模型输出的参数在应用中调用函数。
Dify如何应用Function Calling

插件是一个工具集,包含一个或多个工具 每个工具 = 一个可调用的API
核心机制不变: 模型通过阅读【插件描述】来决定是否调用该插件
插件生态
- 插件分类体系:
- 第三方插件:免费插件 + 付费插件(需要申请API Key)
- 自定义插件(自己创建):集成你需要的任何API
常见插件类别
- 信息查询:搜索、新闻、天气、地图
- 数据分析:股票、汇率、图表生成
- 内容创作:图片生成、视频编辑
- 效率工具:邮件、日历、翻译、计算器
获取当前时间案例
未添加插件:

加了插件之后: 
案例:智能天气助手
什么时候需要自定义插件:
- 官方插件没有你想要的功能
- 付费插件费用太贵
- 想连接特定的第三方API服务
- 需要对接企业内部系统
操作步骤: 
适用场景:个人开发者快速搭建天气查询插件,无需服务器,30分钟内完成
技术栈:FastAPI + localtunnel + Dify
最终效果:在Dify中通过自然语言查询天气,如"北京今天天气如何?"
1.FastAPI 服务搭建
1.1 安装依赖
# 创建虚拟环境(推荐)
python -m venv weather-env
source weather-env/bin/activate # Linux/Mac
# weather-env\Scripts\activate # Windows
# 安装依赖
pip install fastapi uvicorn requests1.2完整代码实现
from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
import requests
app = FastAPI()
# 身份验证令牌(个人使用,简单安全)
VALID_TOKEN = "itcast"
# 城市编码数据(直接硬编码,无需外部文件)
CITY_CODES = {
"北京": "101010100",
"上海": "101020100",
"广州": "101280101",
"深圳": "101280601",
"杭州": "101210101",
"成都": "101270101",
"武汉": "101200101",
"西安": "101110101",
"南京": "101190101",
"重庆": "101040100",
"天津": "101030100",
"苏州": "101190401",
"郑州": "101180101",
"长沙": "101250101",
"青岛": "101120201",
"大连": "101070201",
"宁波": "101210401",
"厦门": "101230201",
"福州": "101230101",
"济南": "101120101",
"合肥": "101220101",
"南昌": "101240101",
"昆明": "101290101",
"南宁": "101300101",
"贵阳": "101260101",
"哈尔滨": "101050101",
"长春": "101060101",
"沈阳": "101070101",
"石家庄": "101090101",
"太原": "101100101",
"呼和浩特": "101080101",
"乌鲁木齐": "101130101",
"拉萨": "101140101",
"兰州": "101110501",
"西宁": "101150101",
"银川": "101170101",
"海口": "101310101",
"三亚": "101310201"
}
class WeatherRequest(BaseModel):
location: str
@app.post("/weather")
def get_current_weather(request: Request, body: WeatherRequest):
"""
天气查询接口
- 需要Authorization头认证
- 返回自然语言格式的天气信息
"""
# 1. 验证身份
auth_header = request.headers.get("Authorization")
if auth_header != f"Bearer {VALID_TOKEN}":
raise HTTPException(status_code=403, detail="Invalid Authorization header")
location = body.location
# 2. 查找城市编码
city_code = CITY_CODES.get(location)
if not city_code:
return {
"status": "error",
"message": f"请提供{location}对应的编码方可查询,目前支持的城市:{','.join(CITY_CODES.keys())}"
}
# 3. 调用天气API
url = f"http://t.weather.itboy.net/api/weather/city/{city_code}"
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
except Exception as e:
return {"status": "error", "message": f"天气服务请求失败: {str(e)}"}
# 4. 解析天气数据
try:
forecast = data["data"]["forecast"][0]
weather_type = forecast["type"]
high = forecast["high"].replace("高温 ", "")
low = forecast["low"].replace("低温 ", "")
temperature = f"{high}/{low}"
# 5. 返回自然语言格式
return f"{location}今天是{weather_type},温度{temperature}"
except (KeyError, IndexError) as e:
return {"status": "error", "message": f"天气数据解析失败: {str(e)}"}
# 启动入口
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8081)1.3 启动服务
python main.py预期输出:
INFO: Uvicorn running on http://0.0.0.0:8081 (Press CTRL+C to quit)2.公网穿透配置
2.1 安装 localtunnel
# 全局安装
npm install -g localtunnel2.2 启动穿透服务
# 新开一个终端窗口
lt --port 8081✅ 预期输出:
your url is: https://bitter-lions-boil.loca.ltyour url is: https://random-name-123.loca.lt
复制这个URL
⚠️ 重要:保持这个终端窗口开启,关闭后链接失效
3.服务测试验证
Postman 测试
创建 POST 请求
URL:
https://your-url.loca.lt/weatherHeaders:
Authorization: Bearer itcastContent-Type: application/json
Body (raw, JSON):
{"location": "北京"}结果: 
4.Dify 插件配置
4.1 OpenAPI 3.1.0 Schema
{
"openapi": "3.0.0",
"info": {
"title": "天气查询API",
"description": "查询中国城市当前天气信息",
"version": "v1.0.0"
},
"servers": [
{
"url": "https://bitter-lions-boil.loca.lt"
}
],
"paths": {
"/weather": {
"post": {
"summary": "查询城市天气",
"operationId": "get_weather",
"security": [
{
"BearerAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称",
"example": "北京"
}
},
"required": ["location"]
}
}
}
},
"responses": {
"200": {
"description": "成功获取天气信息"
}
}
}
}
},
"components": {
"schemas": {},
"securitySchemes": {
"BearerAuth": {
"type": "http",
"scheme": "bearer"
}
}
}
}4.2 Dify 插件创建步骤
- 登录 Dify 控制台
- 选择你的工作空间
- 创建插件
- 导航到 「插件」 → 「创建插件」
- 选择 「OpenAPI」 类型
- 点击 「下一步」
- 配置 OpenAPI Schema
- 将上面的 JSON Schema 完整复制到编辑器中
- 关键步骤:替换
servers.url为你的 localtunnel URL
"servers": [
{
"url": "https://weather-api-abc123.loca.lt", // ← 替换这里!
}
]配置认证
在插件配置页面,找到 「Authentication」 部分
选择 「Bearer Token」 类型
在 「Value」 字段输入:
itcast点击 「保存」
测试插件
在测试区域输入:
{
"location": "北京"
}点击 「测试」 按钮
预期结果:

启用插件
点击 「发布」 按钮
选择要启用该插件的 「应用」
在应用中就可以使用天气查询功能了
5. 在 Dify 应用中使用

6、故障排除指南
常见问题及解决方案
| 问题现象 | 原因分析 | 解决方案 |
|---|---|---|
Reached maximum retries | Dify无法访问localhost | 必须使用公网URL,不能用localhost |
{"detail":"Not Found"} | 路由路径错误 | 检查代码中是@app.post("/weather") |
403 Forbidden | token不匹配 | 确认VALID_TOKEN = "itcast"和Dify配置一致 |
| 连接超时 | localtunnel断开 | 重启lt --port 8081,更新Dify中的URL |
| 城市未找到 | 城市不在CITY_CODES中 | 在代码中添加该城市编码 |
快速诊断命令
# 1. 检查服务是否运行
lsof -i :8081 # Mac/Linux
netstat -ano \| findstr 8081 # Windows
# 2. 检查公网可达性
curl -I https://your-url.loca.lt
# 3. 完整测试命令
curl -X POST https://your-url.loca.lt/weather \
-H "Authorization: Bearer itcast" \
-H "Content-Type: application/json" \
-d '{"location": "杭州"}'7、维护与优化建议
7.1 临时方案(日常使用)
保持终端开启:两个终端(FastAPI + localtunnel)需要一直运行
每日重启:local tunnel 链接24小时后可能失效,每天重启一次
快速更新URL:创建一个脚本自动更新Dify配置
7.2 永久方案(推荐升级)
# 部署到免费云服务(Render.com示例)
# 1. 创建render.com账号
# 2. 创建Web Service
# 3. 连接GitHub仓库
# 4. 设置环境变量(如果需要)
# 5. 部署完成,获取永久URL7.3 功能扩展
添加更多城市:在
CITY_CODES字典中添加新城市丰富天气信息:返回湿度、风力等更多字段
错误重试机制:添加请求重试逻辑
缓存机制:避免频繁请求天气API