feat:天气工具,调整tools

This commit is contained in:
wolter 2025-12-11 17:03:10 +08:00
parent 4b1c297ed3
commit c73327e805
16 changed files with 379 additions and 281 deletions

View File

@ -71,6 +71,10 @@ tools:
zltxOrderAfterSaleResellerBatch: zltxOrderAfterSaleResellerBatch:
enabled: true enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/reseller_pre_ai" base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/afterSales/reseller_pre_ai"
weather:
enabled: true
base_url: "https://restapi.amap.com/v3/weather/weatherInfo"
api_key: "12afbde5ab78cb7e575ff76bd0bdef2b"

View File

@ -131,7 +131,8 @@ func (d *Do) loadSystemInfo(ctx context.Context, client *gateway.Client, require
// 获取任务列表的辅助函数 // 获取任务列表的辅助函数
func (d *Do) loadTaskList(ctx context.Context, client *gateway.Client, requireData *entitys.RequireData) error { func (d *Do) loadTaskList(ctx context.Context, client *gateway.Client, requireData *entitys.RequireData) error {
if taskInfo := client.GetTasks(); len(taskInfo) == 0 { if taskInfo := client.GetTasks(); len(taskInfo) == 0 {
tasks, err := d.GetTasks(requireData.Sys.SysID) // 从数据库获取任务列表, 0 表示获取公共的任务
tasks, err := d.GetTasks(requireData.Sys.SysID, 0)
if err != nil { if err != nil {
return err return err
} }
@ -140,6 +141,7 @@ func (d *Do) loadTaskList(ctx context.Context, client *gateway.Client, requireDa
} else { } else {
requireData.Tasks = taskInfo requireData.Tasks = taskInfo
} }
return nil return nil
} }
@ -242,12 +244,12 @@ func (d *Do) getSessionChatHis(requireData *entitys.RequireData) (his []model.Ai
return return
} }
func (d *Do) GetTasks(sysId int32) (tasks []model.AiTask, err error) { func (d *Do) GetTasks(sysId ...int32) (tasks []model.AiTask, err error) {
cond := builder.NewCond() cond := builder.NewCond()
cond = cond.And(builder.Eq{"sys_id": sysId}) //cond = cond.And(builder.Eq{"sys_id": sysId})
cond = cond.And(builder.IsNull{"delete_at"}) cond = cond.And(builder.IsNull{"delete_at"})
cond = cond.And(builder.Eq{"status": 1}) cond = cond.And(builder.Eq{"status": 1}.And(builder.In("sys_id", sysId)))
_, err = d.taskImpl.GetListToStruct(&cond, nil, &tasks, "") _, err = d.taskImpl.GetListToStruct(&cond, nil, &tasks, "")
return return

View File

@ -12,6 +12,7 @@ import (
"ai_scheduler/internal/pkg/l_request" "ai_scheduler/internal/pkg/l_request"
"ai_scheduler/internal/pkg/mapstructure" "ai_scheduler/internal/pkg/mapstructure"
"ai_scheduler/internal/tools" "ai_scheduler/internal/tools"
"ai_scheduler/internal/tools/public"
"ai_scheduler/internal/tools_bot" "ai_scheduler/internal/tools_bot"
"context" "context"
"encoding/json" "encoding/json"
@ -182,7 +183,7 @@ func (r *Handle) handleKnowle(ctx context.Context, requireData *entitys.RequireD
return fmt.Errorf("tool not found: %s", configData.Tool) return fmt.Errorf("tool not found: %s", configData.Tool)
} }
if knowledgeTool, ok := tool.(*tools.KnowledgeBaseTool); !ok { if knowledgeTool, ok := tool.(*public.KnowledgeBaseTool); !ok {
return fmt.Errorf("未找到知识库Tool: %s", configData.Tool) return fmt.Errorf("未找到知识库Tool: %s", configData.Tool)
} else { } else {
host = knowledgeTool.GetConfig().BaseURL host = knowledgeTool.GetConfig().BaseURL
@ -193,7 +194,7 @@ func (r *Handle) handleKnowle(ctx context.Context, requireData *entitys.RequireD
// 知识库的session为空请求知识库获取, 并绑定 // 知识库的session为空请求知识库获取, 并绑定
if requireData.SessionInfo.KnowlegeSessionID == "" { if requireData.SessionInfo.KnowlegeSessionID == "" {
// 请求知识库 // 请求知识库
if sessionIdKnowledge, err = tools.GetKnowledgeBaseSession(host, requireData.Sys.KnowlegeBaseID, requireData.Sys.KnowlegeTenantKey); err != nil { if sessionIdKnowledge, err = public.GetKnowledgeBaseSession(host, requireData.Sys.KnowlegeBaseID, requireData.Sys.KnowlegeTenantKey); err != nil {
return return
} }

View File

@ -1,121 +0,0 @@
package tools
import (
"ai_scheduler/internal/entitys"
"context"
"encoding/json"
"fmt"
"math"
)
// CalculatorTool 计算器工具
type CalculatorTool struct{}
// NewCalculatorTool 创建计算器工具
func NewCalculatorTool() *CalculatorTool {
return &CalculatorTool{}
}
// Name 返回工具名称
func (c *CalculatorTool) Name() string {
return "calculate"
}
// Description 返回工具描述
func (c *CalculatorTool) Description() string {
return "执行基本的数学运算,支持加减乘除和幂运算"
}
// Definition 返回工具定义
func (c *CalculatorTool) Definition() entitys.ToolDefinition {
return entitys.ToolDefinition{
Type: "function",
Function: entitys.FunctionDef{
Name: c.Name(),
Description: c.Description(),
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"operation": map[string]interface{}{
"type": "string",
"description": "运算类型",
"enum": []string{"add", "subtract", "multiply", "divide", "power"},
},
"a": map[string]interface{}{
"type": "number",
"description": "第一个数字",
},
"b": map[string]interface{}{
"type": "number",
"description": "第二个数字",
},
},
"required": []string{"operation", "a", "b"},
},
},
}
}
// CalculateRequest 计算请求参数
type CalculateRequest struct {
Operation string `json:"operation"`
A float64 `json:"a"`
B float64 `json:"b"`
}
// CalculateResponse 计算响应
type CalculateResponse struct {
Operation string `json:"operation"`
A float64 `json:"a"`
B float64 `json:"b"`
Result float64 `json:"result"`
Expression string `json:"expression"`
}
// Execute 执行计算
func (c *CalculatorTool) Execute(ctx context.Context, args json.RawMessage) (interface{}, error) {
var req CalculateRequest
if err := json.Unmarshal(args, &req); err != nil {
return nil, fmt.Errorf("invalid calculate request: %w", err)
}
var result float64
var expression string
switch req.Operation {
case "add":
result = req.A + req.B
expression = fmt.Sprintf("%.2f + %.2f = %.2f", req.A, req.B, result)
case "subtract":
result = req.A - req.B
expression = fmt.Sprintf("%.2f - %.2f = %.2f", req.A, req.B, result)
case "multiply":
result = req.A * req.B
expression = fmt.Sprintf("%.2f × %.2f = %.2f", req.A, req.B, result)
case "divide":
if req.B == 0 {
return nil, fmt.Errorf("division by zero is not allowed")
}
result = req.A / req.B
expression = fmt.Sprintf("%.2f ÷ %.2f = %.2f", req.A, req.B, result)
case "power":
result = math.Pow(req.A, req.B)
expression = fmt.Sprintf("%.2f ^ %.2f = %.2f", req.A, req.B, result)
default:
return nil, fmt.Errorf("unsupported operation: %s", req.Operation)
}
// 检查结果是否有效
if math.IsNaN(result) || math.IsInf(result, 0) {
return nil, fmt.Errorf("calculation resulted in invalid number")
}
return &CalculateResponse{
Operation: req.Operation,
A: req.A,
B: req.B,
Result: result,
Expression: expression,
}, nil
}

View File

@ -5,6 +5,7 @@ import (
"ai_scheduler/internal/data/constants" "ai_scheduler/internal/data/constants"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/pkg/utils_ollama"
"ai_scheduler/internal/tools/public"
zltxtool "ai_scheduler/internal/tools/zltx" zltxtool "ai_scheduler/internal/tools/zltx"
"context" "context"
@ -44,30 +45,30 @@ func NewManager(config *config.Config, llm *utils_ollama.Client) *Manager {
// 注册直连天下订单详情工具 // 注册直连天下订单详情工具
if config.Tools.ZltxOrderDetail.Enabled { if config.Tools.ZltxOrderDetail.Enabled {
zltxOrderDetailTool := NewZltxOrderDetailTool(config.Tools.ZltxOrderDetail, m.llm) zltxOrderDetailTool := zltxtool.NewZltxOrderDetailTool(config.Tools.ZltxOrderDetail, m.llm)
m.tools[zltxOrderDetailTool.Name()] = zltxOrderDetailTool m.tools[zltxOrderDetailTool.Name()] = zltxOrderDetailTool
} }
//注册直连天下订单日志工具 //注册直连天下订单日志工具
if config.Tools.ZltxOrderDirectLog.Enabled { if config.Tools.ZltxOrderDirectLog.Enabled {
zltxOrderLogTool := NewZltxOrderLogTool(config.Tools.ZltxOrderDirectLog) zltxOrderLogTool := zltxtool.NewZltxOrderLogTool(config.Tools.ZltxOrderDirectLog)
m.tools[zltxOrderLogTool.Name()] = zltxOrderLogTool m.tools[zltxOrderLogTool.Name()] = zltxOrderLogTool
} }
//注册直连天下商品工具 //注册直连天下商品工具
if config.Tools.ZltxProduct.Enabled { if config.Tools.ZltxProduct.Enabled {
zltxProductTool := NewZltxProductTool(config.Tools.ZltxProduct) zltxProductTool := zltxtool.NewZltxProductTool(config.Tools.ZltxProduct)
m.tools[zltxProductTool.Name()] = zltxProductTool m.tools[zltxProductTool.Name()] = zltxProductTool
} }
//注册直连天下订单统计工具 //注册直连天下订单统计工具
if config.Tools.ZltxOrderStatistics.Enabled { if config.Tools.ZltxOrderStatistics.Enabled {
zltxOrderStatisticsTool := NewZltxOrderStatisticsTool(config.Tools.ZltxOrderStatistics) zltxOrderStatisticsTool := zltxtool.NewZltxOrderStatisticsTool(config.Tools.ZltxOrderStatistics)
m.tools[zltxOrderStatisticsTool.Name()] = zltxOrderStatisticsTool m.tools[zltxOrderStatisticsTool.Name()] = zltxOrderStatisticsTool
} }
// 注册知识库工具 // 注册知识库工具
if config.Tools.Knowledge.Enabled { if config.Tools.Knowledge.Enabled {
knowledgeTool := NewKnowledgeBaseTool(config.Tools.Knowledge) knowledgeTool := public.NewKnowledgeBaseTool(config.Tools.Knowledge)
m.tools[knowledgeTool.Name()] = knowledgeTool m.tools[knowledgeTool.Name()] = knowledgeTool
} }
@ -86,9 +87,14 @@ func NewManager(config *config.Config, llm *utils_ollama.Client) *Manager {
zltxOrderAfterSaleResellerBatchTool := zltxtool.NewOrderAfterSaleResellerBatchTool(config.Tools.ZltxOrderAfterSaleResellerBatch) zltxOrderAfterSaleResellerBatchTool := zltxtool.NewOrderAfterSaleResellerBatchTool(config.Tools.ZltxOrderAfterSaleResellerBatch)
m.tools[zltxOrderAfterSaleResellerBatchTool.Name()] = zltxOrderAfterSaleResellerBatchTool m.tools[zltxOrderAfterSaleResellerBatchTool.Name()] = zltxOrderAfterSaleResellerBatchTool
} }
// 注册天气工具
if config.Tools.Weather.Enabled {
weatherTool := public.NewWeatherTool(config.Tools.Weather)
m.tools[weatherTool.Name()] = weatherTool
}
// 普通对话 // 普通对话
chat := NewNormalChatTool(m.llm, config) chat := public.NewNormalChatTool(m.llm, config)
m.tools[chat.Name()] = chat m.tools[chat.Name()] = chat
return m return m

View File

@ -1,4 +1,4 @@
package tools package public
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"

View File

@ -1,4 +1,4 @@
package tools package public
import ( import (
"testing" "testing"

View File

@ -1,4 +1,4 @@
package tools package public
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"

View File

@ -0,0 +1,345 @@
package public
import (
"ai_scheduler/internal/config"
"ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg/l_request"
"log"
"strconv"
"context"
"encoding/json"
"fmt"
"time"
)
// WeatherTool 天气查询工具
type WeatherTool struct {
mockData bool
config config.ToolConfig
}
// NewWeatherTool 创建天气工具
func NewWeatherTool(config config.ToolConfig) *WeatherTool {
return &WeatherTool{config: config}
}
// Name 返回工具名称
func (w *WeatherTool) Name() string {
return "get_weather"
}
// Description 返回工具描述
func (w *WeatherTool) Description() string {
return "获取指定城市的天气信息"
}
// Definition 返回工具定义
func (w *WeatherTool) Definition() entitys.ToolDefinition {
return entitys.ToolDefinition{
Type: "function",
Function: entitys.FunctionDef{
Name: w.Name(),
Description: w.Description(),
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"city": map[string]interface{}{
"type": "string",
"description": "城市名称,如:北京、上海、广州",
},
"unit": map[string]interface{}{
"type": "string",
"description": "温度单位celsius(摄氏度)或fahrenheit(华氏度)",
"enum": []string{"celsius", "fahrenheit"},
"default": "celsius",
},
"extensions": map[string]interface{}{
"type": "string",
"description": "扩展参数base/all base:返回实况天气 all:返回预报天气",
"enum": []string{"base", "all"},
"default": "base",
},
},
"required": []string{"city"},
},
},
}
}
// WeatherRequest 天气请求参数
type WeatherRequest struct {
City string `json:"city"`
Extensions string `json:"extensions"` // 扩展参数base/all base:返回实况天气 all:返回预报天气
Unit string `json:"unit,omitempty"`
}
// WeatherResponse 天气响应
type WeatherResponse struct {
City string `json:"city"`
Unit string `json:"unit"`
Timestamp string `json:"timestamp"`
LiveWeather *LiveWeather `json:"live_weather,omitempty"` // 实时天气
Forecasts []ForecastWeather `json:"forecasts,omitempty"` // 预报天气
}
// ForecastWeather 预报天气
type ForecastWeather struct {
Date string `json:"date"`
Week string `json:"week"`
DayWeather string `json:"day_weather"`
NightWeather string `json:"night_weather"`
DayTemp float64 `json:"day_temp"`
NightTemp float64 `json:"night_temp"`
DayWind string `json:"day_wind"`
NightWind string `json:"night_wind"`
DayWindPower string `json:"day_wind_power"`
NightWindPower string `json:"night_wind_power"`
}
// LiveWeather 实时天气
type LiveWeather struct {
Temperature float64 `json:"temperature"`
Condition string `json:"condition"`
Humidity int `json:"humidity"`
WindSpeed float64 `json:"wind_speed"`
WindDirection string `json:"wind_direction"`
}
// Execute 执行天气查询
func (w *WeatherTool) Execute(ctx context.Context, requireData *entitys.RequireData) error {
var req WeatherRequest
if err := json.Unmarshal([]byte(requireData.Match.Parameters), &req); err != nil {
return fmt.Errorf("invalid weather request: %w", err)
}
if req.City == "" {
return fmt.Errorf("city is required")
}
if req.Unit == "" {
req.Unit = "celsius"
}
// 设置默认获取实时天气信息
if req.Extensions == "" {
req.Extensions = "base"
}
// 这里可以集成真实的天气API
responseMsg, err := w.getRealWeather(req)
if err != nil {
return fmt.Errorf("failed to get real weather: %w", err)
}
// 根据 extensions 参数返回不同的天气信息
if req.Extensions == "base" {
entitys.ResText(requireData.Ch, "", fmt.Sprintf("%s实时天气%s温度%.1f℃,湿度:%d%%,风速:%.1fkm/h风向%s",
req.City,
responseMsg.LiveWeather.Condition,
responseMsg.LiveWeather.Temperature,
responseMsg.LiveWeather.Humidity,
responseMsg.LiveWeather.WindSpeed,
responseMsg.LiveWeather.WindDirection))
} else {
rspStr := fmt.Sprintf("%s天气预报\n", req.City)
for _, forecast := range responseMsg.Forecasts {
rspStr += fmt.Sprintf("%s 温度:%.1f℃/%.1f℃ 风力:%s %s\n",
forecast.Date, forecast.DayTemp, forecast.NightTemp, forecast.DayWind, forecast.NightWind)
}
entitys.ResText(requireData.Ch, "", rspStr)
}
return nil
}
//// getMockWeather 获取模拟天气数据
//func (w *WeatherTool) getMockWeather(city, unit string) *WeatherResponse {
// rand.Seed(time.Now().UnixNano())
//
// // 模拟不同城市的基础温度
// baseTemp := map[string]float64{
// "北京": 15.0,
// "上海": 18.0,
// "广州": 25.0,
// "深圳": 26.0,
// "杭州": 17.0,
// "成都": 16.0,
// }
//
// temp := baseTemp[city]
// if temp == 0 {
// temp = 20.0 // 默认温度
// }
//
// // 添加随机变化
// temp += (rand.Float64() - 0.5) * 10
//
// // 转换温度单位
// if unit == "fahrenheit" {
// temp = temp*9/5 + 32
// }
//
// conditions := []string{"晴朗", "多云", "阴天", "小雨", "中雨"}
// condition := conditions[rand.Intn(len(conditions))]
//
// return &WeatherResponse{
// City: city,
// Temperature: float64(int(temp*10)) / 10, // 保留一位小数
// Unit: unit,
// Condition: condition,
// Humidity: rand.Intn(40) + 40, // 40-80%
// WindSpeed: float64(rand.Intn(20)) + 1.0,
// Timestamp: time.Now().Format("2006-01-02 15:04:05"),
// }
//}
// getRealWeather 调用高德天气API
func (w *WeatherTool) getRealWeather(request WeatherRequest) (*WeatherResponse, error) {
// 构建请求URL
req := l_request.Request{
Url: w.config.BaseURL,
Headers: map[string]string{},
Params: map[string]string{
"city": request.City, // 城市名称
"key": w.config.APIKey, // API密钥
// extensions: 基础天气数据 可选值base/all base:返回实况天气 all:返回预报天气
"extensions": request.Extensions, // 基础天气数据
"output": "JSON", // JSON格式返回
},
Method: "GET",
}
res, err := req.Send()
if err != nil {
return nil, err
}
// 解析API响应
var apiResp struct {
Status string `json:"status"`
Count string `json:"count"`
Info string `json:"info"`
Infocode string `json:"infocode"`
// 预报天气信息数据
Forecasts []struct {
City string `json:"city"`
Adcode string `json:"adcode"`
Province string `json:"province"`
Reporttime string `json:"reporttime"`
Casts []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"`
DaytempFloat string `json:"daytemp_float"`
NighttempFloat string `json:"nighttemp_float"`
} `json:"casts"`
} `json:"forecasts"`
// 实况天气信息数据
Lives []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"`
TemperatureFloat string `json:"temperature_float"`
HumidityFloat string `json:"humidity_float"`
} `json:"lives"`
}
log.Printf("weather API response: %s", string(res.Content))
if err = json.Unmarshal(res.Content, &apiResp); err != nil {
return nil, fmt.Errorf("parse weather API response failed: %w", err)
}
// 检查API返回状态
if apiResp.Status != "1" {
return nil, fmt.Errorf("weather API returned error: %s, info: %s", apiResp.Status, apiResp.Info)
}
// 获取城市名称
cityName := ""
if len(apiResp.Lives) > 0 {
cityName = apiResp.Lives[0].City
} else if len(apiResp.Forecasts) > 0 {
cityName = apiResp.Forecasts[0].City
} else {
return nil, fmt.Errorf("no weather data found")
}
// 构建响应
response := &WeatherResponse{
City: cityName,
Unit: request.Unit,
Timestamp: time.Now().Format("2006-01-02 15:04:05"),
}
// 处理实时天气
if len(apiResp.Lives) > 0 {
liveData := apiResp.Lives[0]
// 转换温度
temp, _ := strconv.ParseFloat(liveData.Temperature, 64)
if request.Unit == "fahrenheit" {
temp = temp*9/5 + 32
}
// 转换湿度和风速
humidity, _ := strconv.Atoi(liveData.Humidity)
windSpeed, _ := strconv.ParseFloat(liveData.Windpower, 64)
response.LiveWeather = &LiveWeather{
Temperature: temp,
Condition: liveData.Weather,
Humidity: humidity,
WindSpeed: windSpeed,
WindDirection: liveData.Winddirection,
}
}
// 处理预报天气
if len(apiResp.Forecasts) > 0 && len(apiResp.Forecasts[0].Casts) > 0 {
response.Forecasts = make([]ForecastWeather, 0, len(apiResp.Forecasts[0].Casts))
for _, cast := range apiResp.Forecasts[0].Casts {
// 转换温度
dayTemp, _ := strconv.ParseFloat(cast.Daytemp, 64)
nightTemp, _ := strconv.ParseFloat(cast.Nighttemp, 64)
if request.Unit == "fahrenheit" {
dayTemp = dayTemp*9/5 + 32
nightTemp = nightTemp*9/5 + 32
}
forecast := ForecastWeather{
Date: cast.Date,
Week: cast.Week,
DayWeather: cast.Dayweather,
NightWeather: cast.Nightweather,
DayTemp: dayTemp,
NightTemp: nightTemp,
DayWind: cast.Daywind,
NightWind: cast.Nightwind,
DayWindPower: cast.Daypower,
NightWindPower: cast.Nightpower,
}
response.Forecasts = append(response.Forecasts, forecast)
}
}
return response, nil
}

View File

@ -1,139 +0,0 @@
package tools
import (
"ai_scheduler/internal/entitys"
"context"
"encoding/json"
"fmt"
"math/rand"
"time"
)
// WeatherTool 天气查询工具
type WeatherTool struct {
mockData bool
}
// NewWeatherTool 创建天气工具
func NewWeatherTool() *WeatherTool {
return &WeatherTool{}
}
// Name 返回工具名称
func (w *WeatherTool) Name() string {
return "get_weather"
}
// Description 返回工具描述
func (w *WeatherTool) Description() string {
return "获取指定城市的天气信息"
}
// Definition 返回工具定义
func (w *WeatherTool) Definition() entitys.ToolDefinition {
return entitys.ToolDefinition{
Type: "function",
Function: entitys.FunctionDef{
Name: w.Name(),
Description: w.Description(),
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"city": map[string]interface{}{
"type": "string",
"description": "城市名称,如:北京、上海、广州",
},
"unit": map[string]interface{}{
"type": "string",
"description": "温度单位celsius(摄氏度)或fahrenheit(华氏度)",
"enum": []string{"celsius", "fahrenheit"},
"default": "celsius",
},
},
"required": []string{"city"},
},
},
}
}
// WeatherRequest 天气请求参数
type WeatherRequest struct {
City string `json:"city"`
Unit string `json:"unit,omitempty"`
}
// WeatherResponse 天气响应
type WeatherResponse struct {
City string `json:"city"`
Temperature float64 `json:"temperature"`
Unit string `json:"unit"`
Condition string `json:"condition"`
Humidity int `json:"humidity"`
WindSpeed float64 `json:"wind_speed"`
Timestamp string `json:"timestamp"`
}
// Execute 执行天气查询
func (w *WeatherTool) Execute(ctx context.Context, args json.RawMessage) (interface{}, error) {
var req WeatherRequest
if err := json.Unmarshal(args, &req); err != nil {
return nil, fmt.Errorf("invalid weather request: %w", err)
}
if req.City == "" {
return nil, fmt.Errorf("city is required")
}
if req.Unit == "" {
req.Unit = "celsius"
}
if w.mockData {
return w.getMockWeather(req.City, req.Unit), nil
}
// 这里可以集成真实的天气API
return w.getMockWeather(req.City, req.Unit), nil
}
// getMockWeather 获取模拟天气数据
func (w *WeatherTool) getMockWeather(city, unit string) *WeatherResponse {
rand.Seed(time.Now().UnixNano())
// 模拟不同城市的基础温度
baseTemp := map[string]float64{
"北京": 15.0,
"上海": 18.0,
"广州": 25.0,
"深圳": 26.0,
"杭州": 17.0,
"成都": 16.0,
}
temp := baseTemp[city]
if temp == 0 {
temp = 20.0 // 默认温度
}
// 添加随机变化
temp += (rand.Float64() - 0.5) * 10
// 转换温度单位
if unit == "fahrenheit" {
temp = temp*9/5 + 32
}
conditions := []string{"晴朗", "多云", "阴天", "小雨", "中雨"}
condition := conditions[rand.Intn(len(conditions))]
return &WeatherResponse{
City: city,
Temperature: float64(int(temp*10)) / 10, // 保留一位小数
Unit: unit,
Condition: condition,
Humidity: rand.Intn(40) + 40, // 40-80%
WindSpeed: float64(rand.Intn(20)) + 1.0,
Timestamp: time.Now().Format("2006-01-02 15:04:05"),
}
}

View File

@ -1,4 +1,4 @@
package tools package zltx
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"

View File

@ -1,4 +1,4 @@
package tools package zltx
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"

View File

@ -1,4 +1,4 @@
package tools package zltx
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"

View File

@ -1,4 +1,4 @@
package tools package zltx
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"

View File

@ -1,4 +1,4 @@
package tools package zltx
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"

View File

@ -1,4 +1,4 @@
package tools package zltx
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"