Commit 031dfa1e by tinywell

1设备传感器数量查询接口接入;问题类型识别参数说明优化;工具返回数据结构精简

parent a086b59c
...@@ -161,7 +161,7 @@ class MonitorClient(BaseHttpClient): ...@@ -161,7 +161,7 @@ class MonitorClient(BaseHttpClient):
"deviceType": device_type "deviceType": device_type
} }
) )
return BaseResponse[List](**data) return BaseResponse[Dict](**data)
# 示例:添加新的数据接口客户端 # 示例:添加新的数据接口客户端
class RateClient(BaseHttpClient): class RateClient(BaseHttpClient):
......
...@@ -5,7 +5,9 @@ from langchain_core.tools import BaseTool ...@@ -5,7 +5,9 @@ from langchain_core.tools import BaseTool
from .http_tools import MonitorClient, RateClient from .http_tools import MonitorClient, RateClient
from typing import Type from typing import Type
from ..utils.logger import get_logger from ..utils.logger import get_logger
from .code import AreaCodeTool
code_tool = AreaCodeTool()
class MonitorPointResponse(): class MonitorPointResponse():
"""监测点查询结果""" """监测点查询结果"""
status: str = Field(..., description="状态") status: str = Field(..., description="状态")
...@@ -15,15 +17,17 @@ class MonitorPointResponse(): ...@@ -15,15 +17,17 @@ class MonitorPointResponse():
class MonitorPointArgs(BaseModel): class MonitorPointArgs(BaseModel):
"""监测点查询参数""" """监测点查询参数"""
key: str = Field(..., description="行政区划名称(省/市级别均可,只需要最后一级,如长沙市,不需要湖南省)") key: str = Field(..., description="行政区划名称(省/市级别均可,只需要最后一级,如长沙市,不需要湖南省)")
year: str = Field("", description="年份,未提及则为空") start_time: str = Field("", description="可选参数:仅当需要查询特定时间区间的监测点数据时才需要指定,默认为空")
disaster_type: str = Field("", description="灾害类型,如崩塌、滑坡、泥石流、地面塌陷、地面沉降、地裂缝等,未提及则为空") end_time: str = Field("", description="可选参数:仅当需要查询特定时间区间的监测点数据时才需要指定,默认为空")
disaster_type: str = Field("", description="需要查询的灾害类型,如崩塌、滑坡、泥石流、地面塌陷、地面沉降、地裂缝等,默认为空")
three_d_model: str = Field("", description="是否需要三维模型,需要为有,不需要为无,默认为空") three_d_model: str = Field("", description="是否需要三维模型,需要为有,不需要为无,默认为空")
ortho_image: str = Field("", description="是否需要正射影像,需要为有,不需要为无,默认为空") ortho_image: str = Field("", description="是否需要正射影像,需要为有,不需要为无,默认为空")
disaster_threat_people_range_start: str = Field("", description="灾害威胁人数范围起始值,如100,未提及则为空") disaster_threat_people_range_start: str = Field("", description="灾害威胁人数范围起始值,如100,默认为空")
disaster_threat_people_range_end: str = Field("", description="灾害威胁人数范围结束值,如200,未提及则为空") disaster_threat_people_range_end: str = Field("", description="灾害威胁人数范围结束值,如200,默认为空")
disaster_scale_start: str = Field("", description="灾害规模范围起始值,灾害为崩塌、滑坡、泥石流时表示体积,灾害为地面塌陷、地面沉降时表示面积,为地裂缝时表示长度,未提及则为空") disaster_scale_start: str = Field("", description="灾害规模范围起始值,灾害为崩塌、滑坡、泥石流时表示体积,灾害为地面塌陷、地面沉降时表示面积,为地裂缝时表示长度,默认为空")
disaster_scale_end: str = Field("", description="灾害规模范围结束值,灾害为崩塌、滑坡、泥石流时表示体积,灾害为地面塌陷、地面沉降时表示面积,为地裂缝时表示长度,未提及则为空") disaster_scale_end: str = Field("", description="灾害规模范围结束值,灾害为崩塌、滑坡、泥石流时表示体积,灾害为地面塌陷、地面沉降时表示面积,为地裂缝时表示长度,默认为空")
device_type: str = Field("", description="设备类型(例如 加速度、位移、温度、湿度、裂缝计等),默认为空") device_type: str = Field("", description="设备类型或者传感器类型,当查询设备或传感器信息时需要(例如 加速度、位移、温度、湿度、裂缝计、雨量等),默认为空")
class MonitorPointTool(BaseTool): class MonitorPointTool(BaseTool):
"""查询监测点信息的工具""" """查询监测点信息的工具"""
...@@ -32,7 +36,7 @@ class MonitorPointTool(BaseTool): ...@@ -32,7 +36,7 @@ class MonitorPointTool(BaseTool):
可以查询任意省/市/区县级别的监测点数据,也可以通过灾害类型、灾害规模、灾害威胁人数范围、设备类型等条件查询。 可以查询任意省/市/区县级别的监测点数据,也可以通过灾害类型、灾害规模、灾害威胁人数范围、设备类型等条件查询。
输入参数为行政区划名称,如:湖南省、长沙市、岳麓区等。 输入参数为行政区划名称,如:湖南省、长沙市、岳麓区等。
返回该区域内的监测点列表,包含位置、经纬度等详细信息。 返回该区域内的监测点列表,包含位置、经纬度等详细信息。
还可以查询监测点下相关监测设备信息,比如设备数量等。 还可以查询监测点下相关监测设备、传感器信息,比如设备数量、传感器数量等。
""" """
args_schema: Type[BaseModel] = MonitorPointArgs args_schema: Type[BaseModel] = MonitorPointArgs
client: Any = Field(None, exclude=True) client: Any = Field(None, exclude=True)
...@@ -50,16 +54,18 @@ class MonitorPointTool(BaseTool): ...@@ -50,16 +54,18 @@ class MonitorPointTool(BaseTool):
self.client = MonitorClient(base_url=base_url) self.client = MonitorClient(base_url=base_url)
self.logger = get_logger("MonitorPointTool") self.logger = get_logger("MonitorPointTool")
def _run(self, key: str, year: str = "", disaster_type: str = "", def _run(self, key: str, start_time: str = "", end_time: str = "", disaster_type: str = "",
three_d_model: str = "", ortho_image: str = "", three_d_model: str = "", ortho_image: str = "",
disaster_threat_people_range_start: str = "", disaster_threat_people_range_end: str = "", disaster_threat_people_range_start: str = "", disaster_threat_people_range_end: str = "",
disaster_scale_start: str = "", disaster_scale_end: str = "", device_type: str = "") -> Dict[str, Any]: disaster_scale_start: str = "", disaster_scale_end: str = "", device_type: str = "",
query_type: str = "points") -> Dict[str, Any]:
""" """
执行监测点查询 执行监测点查询
Args: Args:
key: 行政区划名称 key: 行政区划名称
year: 年份 start_time: 开始时间
end_time: 结束时间
disaster_type: 灾害类型 disaster_type: 灾害类型
three_d_model: 是否需要三维模型 three_d_model: 是否需要三维模型
ortho_image: 是否需要正射影像 ortho_image: 是否需要正射影像
...@@ -67,23 +73,97 @@ class MonitorPointTool(BaseTool): ...@@ -67,23 +73,97 @@ class MonitorPointTool(BaseTool):
disaster_threat_people_range_end: 灾害威胁人数范围结束值 disaster_threat_people_range_end: 灾害威胁人数范围结束值
disaster_scale_start: 灾害规模范围起始值 disaster_scale_start: 灾害规模范围起始值
disaster_scale_end: 灾害规模范围结束值 disaster_scale_end: 灾害规模范围结束值
device_required: 是否需要设备相关信息
device_type: 设备类型 device_type: 设备类型
query_type: 查询类型
Returns: Returns:
Dict: 包含查询结果的字典 Dict: 包含查询结果的字典
""" """
if len(device_type) > 0:
query_type = "2"
if query_type == "2":
return self._get_device_info(key, start_time, end_time, device_type)
else:
year = start_time.split("-")[0]
return self._get_points_info(key, year, disaster_type, three_d_model, ortho_image, disaster_threat_people_range_start, disaster_threat_people_range_end, disaster_scale_start, disaster_scale_end, device_type)
def _get_device_info(self, key: str, start_time: str = "", end_time: str = "", device_type: str = ""):
self.logger.info(f"开始查询设备信息,区域: {key}")
code = ""
if key != "":
self.logger.debug(f"查找区域代码: {key}")
codes = code_tool.find_code(key)
if codes is None or len(codes) == 0:
error_msg = f'未找到匹配的区域代码: {key}'
self.logger.warning(error_msg)
return {'code': 400, 'message': error_msg}
code = codes[0][1]
self.logger.debug(f"找到区域代码: {code}")
try:
response = self.client.query_device_and_sensor(code, start_time, end_time, device_type)
self.logger.debug(f"API响应: {response}")
if response.type != 1 or len(response.resultdata) == 0:
error_msg = f"查询失败: {response.message},请检查是否有相关数据权限"
self.logger.warning(error_msg)
return {
'code': 400,
'message': error_msg
}
self.logger.info(f"查询设备信息成功,设备数量: {len(response.resultdata['DeviceList'])}")
devices_info = []
for device in response.resultdata["DeviceList"]:
devices_info.append({
"设备编号": device["DEVICECODE"],
"设备名称": device["DEVICETYPENAME"],
# "GUID": device["GUID"]
})
self.logger.debug(f"处理设备数据: {devices_info}")
sensors_info = []
for sensor in response.resultdata["SensorList"]:
sensors_info.append({
"传感器编号": sensor["SENSORCODE"],
"传感器名称": sensor["DEVICETYPENAME"],
# "GUID": sensor["GUID"]
})
self.logger.debug(f"处理传感器数据: {sensors_info}")
device_table_header = list(devices_info[0].keys())
device_table_data = []
for item in devices_info:
device_table_data.append(list(item.values()))
sensor_table_header = list(sensors_info[0].keys())
sensor_table_data = []
for item in sensors_info:
sensor_table_data.append(list(item.values()))
result = {
'code': 200,
'message': f"在{key}找到{len(devices_info)}个设备信息, {len(sensors_info)}个传感器信息",
# 'devices': {
# 'table_header': device_table_header,
# 'table_data': device_table_data
# },
# 'sensors': {
# 'table_header': sensor_table_header,
# 'table_data': sensor_table_data
# }
}
return result
except Exception as e:
error_msg = f"查询失败: {str(e)}"
self.logger.error(error_msg, exc_info=True)
return {
'code': 400,
'message': error_msg
}
def _get_points_info(self, key: str, year: str = "", disaster_type: str = "",
three_d_model: str = "", ortho_image: str = "",
disaster_threat_people_range_start: str = "", disaster_threat_people_range_end: str = "",
disaster_scale_start: str = "", disaster_scale_end: str = "", device_type: str = ""):
try: try:
self.logger.info(f"开始查询监测点信息,区域: {key}") self.logger.info(f"开始查询监测点信息,区域: {key}")
# code = ""
# if key != "":
# self.logger.debug(f"查找区域代码: {key}")
# codes = code_tool.find_code(key)
# if codes is None or len(codes) == 0:
# error_msg = f'未找到匹配的区域代码: {key}'
# self.logger.warning(error_msg)
# return {'code': 400, 'message': error_msg}
# code = codes[0][1]
# self.logger.debug(f"找到区域代码: {code}")
response = self.client.query_points_sync(key, year, response = self.client.query_points_sync(key, year,
disaster_type, three_d_model, ortho_image, disaster_type, three_d_model, ortho_image,
...@@ -130,10 +210,18 @@ class MonitorPointTool(BaseTool): ...@@ -130,10 +210,18 @@ class MonitorPointTool(BaseTool):
self.logger.info(f"成功获取 {len(points_info)} 个监测点数据") self.logger.info(f"成功获取 {len(points_info)} 个监测点数据")
# markdown = self.to_markdown(points_info) # markdown = self.to_markdown(points_info)
table_header = list(points_info[0].keys())
table_data = []
for item in points_info:
table_data.append(list(item.values()))
result = { result = {
'code': 200, 'code': 200,
'message': f"在{key}找到{len(points_info)}个监测点信息", 'message': f"在{key}找到{len(points_info)}个监测点信息",
'points': points_info, 'points': {
'table_header': table_header,
'table_data': table_data
},
# 'markdown': markdown # 'markdown': markdown
} }
self.logger.info("数据处理完成,返回结果") self.logger.info("数据处理完成,返回结果")
......
...@@ -124,11 +124,25 @@ class RegionRateTool(BaseRateTool): ...@@ -124,11 +124,25 @@ class RegionRateTool(BaseRateTool):
for item in df.resultdata: for item in df.resultdata:
rate_date = self._extract_rate_data(item) rate_date = self._extract_rate_data(item)
result_data.append(rate_date) result_data.append(rate_date)
sorted_data = [rate_date[0]]
if len(result_data) > 1:
sorted_data.extend(sorted(result_data[1:], key=lambda x: x['在线率']))
# 将数据改成表格形式,表头提取之后,数据一行行显示
table_header = list(result_data[0].keys())
table_data = []
for item in result_data:
table_data.append(list(item.values()))
result_data = {
'table_header': table_header,
'table_data': table_data
}
data = { data = {
'region': region_name, 'region': region_name,
'region_code': code, 'region_code': code,
'rate_data': result_data, 'rate_data': result_data,
} }
total_time = time.time() - agent_start total_time = time.time() - agent_start
...@@ -160,6 +174,16 @@ class RegionRateTool(BaseRateTool): ...@@ -160,6 +174,16 @@ class RegionRateTool(BaseRateTool):
self.logger.debug(f"查询结果: {df.resultdata}") self.logger.debug(f"查询结果: {df.resultdata}")
# markdown = self.to_markdown(df.resultdata) # markdown = self.to_markdown(df.resultdata)
table_header = list(result_data[0].keys())
table_data = []
for item in result_data:
table_data.append(list(item.values()))
result_data = {
'table_header': table_header,
'table_data': table_data
}
data = { data = {
'region': region_name, 'region': region_name,
......
...@@ -26,7 +26,7 @@ DEFAULT_CONFIG = { ...@@ -26,7 +26,7 @@ DEFAULT_CONFIG = {
"API_BASE": "http://192.168.10.14:8000/v1", "API_BASE": "http://192.168.10.14:8000/v1",
"TOOL_BASE_URL": "http://localhost:5001", "TOOL_BASE_URL": "http://localhost:5001",
"API_KEY": "xxxxxxxxxxxxx", "API_KEY": "xxxxxxxxxxxxx",
"LOG_LEVEL": "DEBUG" "LOG_LEVEL": "INFO"
} }
def get_config(key: str, args: Optional[argparse.Namespace] = None) -> str: def get_config(key: str, args: Optional[argparse.Namespace] = None) -> str:
......
...@@ -80,10 +80,20 @@ def run_examples(): ...@@ -80,10 +80,20 @@ def run_examples():
"expected": { "expected": {
"tool": "monitor_points_query", "tool": "monitor_points_query",
"params": { "params": {
"key": "甘肃省陇南市" "key": "甘肃省"
} }
} }
}, },{
"query": "贵阳市的雨量传感器有多少",
"expected": {
"tool": "monitor_points_query",
"params": {
"key": "贵阳市",
"device_type": "雨量",
"query_type": "2",
}
}
}
] ]
# 为每个测试案例创建一个表格 # 为每个测试案例创建一个表格
...@@ -120,10 +130,10 @@ def run_examples(): ...@@ -120,10 +130,10 @@ def run_examples():
"✓" if expected_value == actual_value else "✗" "✓" if expected_value == actual_value else "✗"
) )
# run tool # # run tool
tool = tools_dict[actual_tool] # tool = tools_dict[actual_tool]
result = tool.invoke(result["params"]) # result = tool.invoke(result["params"])
print(result) # print(result)
except Exception as e: except Exception as e:
table.add_row("错误", "", str(e), "✗") table.add_row("错误", "", str(e), "✗")
......
...@@ -44,6 +44,7 @@ def run_examples(): ...@@ -44,6 +44,7 @@ def run_examples():
"start_time": "2024-04-01 00:00:00", "start_time": "2024-04-01 00:00:00",
"end_time": "2024-05-31 23:59:59", "end_time": "2024-05-31 23:59:59",
"region_name": "甘肃省", "region_name": "甘肃省",
"query_type": "1",
} }
} }
},{ },{
...@@ -64,6 +65,7 @@ def run_examples(): ...@@ -64,6 +65,7 @@ def run_examples():
"start_time": "2024-01-01 00:00:00", "start_time": "2024-01-01 00:00:00",
"end_time": "2024-12-31 23:59:59", "end_time": "2024-12-31 23:59:59",
"region_name": "甘肃省", "region_name": "甘肃省",
"query_type": "2",
} }
} }
},{ },{
...@@ -74,6 +76,7 @@ def run_examples(): ...@@ -74,6 +76,7 @@ def run_examples():
"start_time": "2024-01-01 00:00:00", "start_time": "2024-01-01 00:00:00",
"end_time": "2024-06-30 23:59:59", "end_time": "2024-06-30 23:59:59",
"region_name": "甘肃省", "region_name": "甘肃省",
"query_type": "1",
} }
} }
} }
...@@ -113,11 +116,11 @@ def run_examples(): ...@@ -113,11 +116,11 @@ def run_examples():
"✓" if expected_value == actual_value else "✗" "✓" if expected_value == actual_value else "✗"
) )
tool = tool_dict[result["tool"]] # tool = tool_dict[result["tool"]]
params = result["params"] # params = result["params"]
result = tool.invoke(params) # result = tool.invoke(params)
print(result) # print(result)
except Exception as e: except Exception as e:
table.add_row("错误", "", str(e), "✗") table.add_row("错误", "", str(e), "✗")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment