首页 > 教程攻略 > ai教程 >Dify 自定义插件实战:FastAPI + localtunnel 30 分钟搭一个天气查询工具

Dify 自定义插件实战:FastAPI + localtunnel 30 分钟搭一个天气查询工具

来源:互联网 时间:2026-07-26 07:33:19

为什么写这篇 / 适合谁看

先说个背景。在 Dify 里想让大模型“查天气”的时候,卡了两个问题:一是插件到底和 Function Calling 是什么关系,二是本地写好的接口,云端 Dify 根本访问不到 localhost

Dify 自定义插件实战:FastAPI + localtunnel 30 分钟搭一个天气查询工具

如果你也想给 Dify 挂一个自己的工具(查天气只是例子,换成查库存、查订单、调任意内部接口都一样),但不想先租服务器,这篇就是给你的。技术栈:FastAPI + localtunnel + Dify,30 分钟能跑通一个能用的自定义插件。

一、先理清概念:插件和 Function Calling 是什么关系

一句话总结:在 Dify 里,工具(插件)就是 Function Calling 的具体实现形式。

大模型本身只会“说话”,要让它能查天气、查数据库、调外部接口,就得给它挂上工具,由模型自己决定何时调用、传什么参数。整体路径很简单:

写一个 HTTP 接口 → 用 OpenAPI Schema 描述给 Dify → 模型按需调用

自定义接口开发的整体流程可以拆成6个步骤,对照着看会更清楚:

步骤 操作 说明
Step 1 脚本开发 本地用 Python 实现接口逻辑
Step 2 运行脚本 后台跑起 API 服务
Step 3 创建工具 在 Dify 工具中创建自定义工具
Step 4 Schema 配置 配置 OpenAPI Schema
Step 5 测试 输入参数测试功能
Step 6 保存 在 Agent 中应用插件

二、FastAPI 服务搭建

2.1 安装依赖

先创建虚拟环境(推荐做,别偷懒),然后装几个必要的包:

# 创建虚拟环境(推荐)
python -m venv weather-env
source weather-env/bin/activate  # Linux/Mac
# weather-envScriptsactivate # Windows
pip install fastapi uvicorn requests

2.2 完整代码(main.py)

城市编码直接硬编码,不依赖外部文件,方便一份文件跑起来:

from fastapi import FastAPI, Request, HTTPException
from pydantic import BaseModel
import requests

app = FastAPI()

# 身份验证令牌(个人使用,随便设一个自己知道的)
VALID_TOKEN = "my-secret-token"

# 城市编码(按需补充)
CITY_CODES = {
    "北京": "101010100",
    "上海": "101020100",
    "广州": "101280101",
    "深圳": "101280601",
    "杭州": "101210101",
    "成都": "101270101",
    # ……可继续补充
}

class WeatherRequest(BaseModel):
    location: str

@app.post("/weather")
def get_current_weather(request: Request, body: WeatherRequest):
    # 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("低温 ", "")
        return f"{location}今天是{weather_type},温度{high}/{low}"
    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)

2.3 启动服务

运行命令:

python main.py

跑起来应该能看到 Uvicorn running on http://0.0.0.0:8081,说明服务正常启动了。

三、公网穿透:让云端 Dify 能访问你的本机

⚠️ 这步最容易被卡住。 Dify(尤其云端版)访问不到你本机的 localhost,必须给它一个公网可达的 URL。localtunnel 就是把本地端口临时映射到公网的小工具,非常方便。

# 全局安装
npm install -g localtunnel

# 新开一个终端窗口
lt --port 8081

输出形如:your url is: https://random-name-123.loca.lt,把这个 URL 复制下来。

❌ 别关这个终端:窗口一关,链接立刻失效。

四、发到 Dify 前先自测

用 curl(或 Postman)先确认接口通,别等配到 Dify 再排错,那是浪费感情:

curl -X POST https://your-url.loca.lt/weather \
  -H "Authorization: Bearer my-secret-token" \
  -H "Content-Type: application/json" \
  -d '{"location": "杭州"}'

五、Dify 插件配置

5.1 OpenAPI 3.1.0 Schema

把下面的 JSON 配置准备好,这是 Dify 认识你接口的“说明书”:

{
  "openapi": "3.1.0",
  "info": {
    "title": "天气查询API",
    "description": "查询中国城市当前天气信息",
    "version": "v1.0.0"
  },
  "servers": [
    { "url": "https://your-url.loca.lt" }
  ],
  "paths": {
    "/weather": {
      "post": {
        "summary": "查询城市天气",
        "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" }
    }
  }
}

5.2 创建步骤

  1. 登录 Dify 控制台,进入「工具」→「自定义」
  2. 把上面的 JSON 完整粘进 Schema 编辑器
  3. ⚠️ 把 servers.url 换成你自己的 localtunnel URL(这一步最容易忘,忘了就一直调不通)
  4. 鉴权方式选「请求头」→ 类型「Bearer」→ Value 填你的 VALID_TOKEN
  5. 在测试区输入 {"location": "深圳"},能返回天气就成了
  6. 点「发布」,选择要启用该插件的应用

六、在 Agent 里用起来

在应用的提示词里加一句引导,模型才知道什么时候调。然后在「工具」里启用这个插件。对话示例:

七、踩坑记录:5 个最容易翻车的地方

现象 原因 解决
❌ Reached maximum retries Dify 访问不到 localhost 必须用公网 URL,不能填 localhost
{"detail":"Not Found"} 路由路径不对 确认代码里是 @app.post("/weather")
❌ 403 Forbidden token 不匹配 Dify 里填的 Bearer 值要和 VALID_TOKEN 一致
❌ 连接超时 localtunnel 断了 重启 lt --port 8081,并更新 Dify 里的 URL
❌ 城市未找到 城市不在 CITY_CODES 在字典里补上该城市编码

八、从临时到永久

localtunnel 适合验证阶段,缺点是链接可能 24 小时失效、终端得一直开着。验证跑通后,把 FastAPI 服务部署到免费云(如 Render)拿一个永久 URL,再把 Dify Schema 里的 servers.url 换成它即可,代码一行不用改。

一句话总结

Dify 自定义插件本质就是:把一个 HTTP 接口用 OpenAPI Schema 描述给大模型,模型按需 Function Calling 调用。 本地 FastAPI 写逻辑、localtunnel 暴露公网、Dify 配 Schema + Bearer 鉴权,三步跑通;验证可行后再迁云端做永久部署。