天气预报工具

2026年1月12日 · 559 字 · 3 分钟

通过高德api获取天气预报,并封装成eino工具

天气预报工具

使用高德的天气api服务封装一个Eino工具,接口文档

先定义请求返回的结构体

ai真的太好用了

// 顶层响应
type WeatherResponse struct {
	Status    string     `json:"status"`              // "1"成功 / "0"失败
	Count     string     `json:"count"`               // 返回结果总数目
	Info      string     `json:"info"`                // 状态信息
	Infocode  string     `json:"infocode"`            // 状态码,"10000"代表正确
	Lives     []Live     `json:"lives,omitempty"`     // 实况天气数据
	Forecasts []Forecast `json:"forecasts,omitempty"` // 预报天气信息数据
}

// 实况 lives 元素
type Live struct {
	Province      string `json:"province"`      // 省份名
	City          string `json:"city"`          // 城市名
	Adcode        string `json:"adcode"`        // 区域编码
	Weather       string `json:"weather"`       // 天气现象(汉字描述)
	Temperature   string `json:"temperature"`   // 实时气温(摄氏度)
	WindDirection string `json:"winddirection"` // 风向描述
	WindPower     string `json:"windpower"`     // 风力级别(级)
	Humidity      string `json:"humidity"`      // 空气湿度
	ReportTime    string `json:"reporttime"`    // 数据发布时间
}

// 预报 forecasts 元素
type Forecast struct {
	City       string `json:"city"`       // 城市名称
	Adcode     string `json:"adcode"`     // 城市编码
	Province   string `json:"province"`   // 省份名称
	ReportTime string `json:"reporttime"` // 预报发布时间
	Casts      []Cast `json:"casts"`      // 预报数据 list(当天/第二天/第三天/第四天)
}

// casts 元素
type Cast struct {
	Date         string `json:"date"`         // 日期
	Week         string `json:"week"`         // 星期几
	DayWeather   string `json:"dayweather"`   // 白天天气现象
	NightWeather string `json:"nightweather"` // 晚上天气现象
	DayTemp      string `json:"daytemp"`      // 白天温度
	NightTemp    string `json:"nighttemp"`    // 晚上温度
	DayWind      string `json:"daywind"`      // 白天风向
	NightWind    string `json:"nightwind"`    // 晚上风向
	DayPower     string `json:"daypower"`     // 白天风力
	NightPower   string `json:"nightpower"`   // 晚上风力
}

请求函数

func WeatherForcast(GaodeCityCode string, live bool) *WeatherResponse {
	url := fmt.Sprintf("https://restapi.amap.com/v3/weather/weatherInfo?key=%s&city=%s", GAODE_KEY, GaodeCityCode)
	if live {
		url += "&extensions=base"
	} else {
		url += "&extensions=all"
	}
	data, err := HttpGet(url) //HttpGet这个函数就是封装了一下http的get请求,返回body
	if err != nil {
		return nil
	}
	var weather WeatherResponse
	err = sonic.Unmarshal(data, &weather)
	if err != nil {
		return nil
	}
	if weather.Status != "1" {
		return nil
	}
	return &weather
}

封装工具函数

type WeatherRequest struct {
	GaodeCityCode string `json:"gaode_city_code" jsonschema:"required,description=城市编码"`
	//也可以把description拿出来单独写成jsonschema_description,enum=xxx是枚举,只能从这些取值
	Day int `json:"live" jsonschema:"required,enum=0,enum=1,enum=2,enum=3,enum=4" jsonschema_description="0代表获取实时天气,1代表今天的,2代表明天的,依次类推,最大只能到4"`
}

func CreateWeatherTool() tool.InvokableTool {
	weatherTool, err := utils.InferTool("weather_tool", "获取天气预报", func(ctx context.Context, request *WeatherRequest) (string, error) {
		if request.Day == 0 {
			weather := WeatherForcast(request.GaodeCityCode, true)
			if weather == nil {
				return "", fmt.Errorf("get weather failed")
			}
			live := weather.Lives[0]
			result := fmt.Sprintf("实时天气: %s, 温度: %s℃, 湿度: %s, 风向: %s, 风力: %s", live.Weather, live.Temperature, live.Humidity, live.WindDirection, live.WindPower)
			return result, nil
		} else if request.Day >= 1 && request.Day <= 4 {
			weather := WeatherForcast(request.GaodeCityCode, false)
			if weather == nil {
				return "", fmt.Errorf("get weather failed")
			}
			forecast := weather.Forecasts[0].Casts[request.Day-1]
			result := fmt.Sprintf(
				"天气预报: 白天天气: %s, 夜晚天气: %s, 白天温度: %s℃, 夜晚温度: %s℃, 白天风向: %s, 夜晚风向: %s, 白天风力: %s, 夜晚风力: %s",
				forecast.DayWeather,
				forecast.NightWeather,
				forecast.DayTemp,
				forecast.NightTemp,
				forecast.DayWind,
				forecast.NightWind,
				forecast.DayPower,
				forecast.NightPower,
			)
			return result, nil
		} else {
			return "", fmt.Errorf("invalid day: %d", request.Day)
		}
	})
	if err != nil {
		log.Fatal(fmt.Errorf("failed to infer tool: %w", err))
	}
	return weatherTool
}

调用工具函数

func useWeatherTool(day int) {
	ctx := context.Background()
	//创建工具
	weatherTool := CreateWeatherTool()
	//创建请求参数
	request := &WeatherRequest{
		GaodeCityCode: "150000",
		Day:           day,
	}
	//json序列化
	jsonRequest, err := sonic.Marshal(request)
	if err != nil {
		log.Fatal(fmt.Errorf("failed to marshal request: %w", err))
	}
	//调用工具
	response, err := weatherTool.InvokableRun(ctx, string(jsonRequest))
	if err != nil {
		log.Fatal(fmt.Errorf("failed to invoke tool: %w", err))
	}
	fmt.Println(response)
}

func main() {
	useWeatherTool(0)
	time.Sleep(1 * time.Second)
	useWeatherTool(1)
	time.Sleep(1 * time.Second)
	useWeatherTool(2)
	time.Sleep(1 * time.Second)
	useWeatherTool(3)
	time.Sleep(1 * time.Second)
	useWeatherTool(4)
}

调用结果

实时天气: 晴, 温度: -5℃, 湿度: 35, 风向: 东南, 风力: ≤3
天气预报: 白天天气: 多云, 夜晚天气: 晴, 白天温度: 0℃, 夜晚温度: -14℃, 白天风向: 西, 夜晚风向: 西, 白天风力: 1-3, 夜晚风力: 1-3
天气预报: 白天天气: 晴, 夜晚天气: 晴, 白天温度: 0℃, 夜晚温度: -11℃, 白天风向: 西南, 夜晚风向: 西南, 白天风力: 1-3, 夜晚风力: 1-3
天气预报: 白天天气: 晴, 夜晚天气: 晴, 白天温度: 2℃, 夜晚温度: -11℃, 白天风向: 西, 夜晚风向: 西, 白天风力: 1-3, 夜晚风力: 1-3