mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-17 01:11:14 +03:00
Add tool to chat
This commit is contained in:
parent
a5a7523379
commit
06446d4c63
@ -140,6 +140,62 @@ def get_tool_definitions() -> List[Dict[str, Any]]:
|
|||||||
"required": [],
|
"required": [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "function",
|
||||||
|
"function": {
|
||||||
|
"name": "set_camera_state",
|
||||||
|
"description": (
|
||||||
|
"Change a camera's feature state (e.g., turn detection on/off, enable/disable recordings). "
|
||||||
|
"Use camera='*' to apply to all cameras at once. "
|
||||||
|
"Only call this tool when the user explicitly asks to change a camera setting. "
|
||||||
|
"Requires admin privileges."
|
||||||
|
),
|
||||||
|
"parameters": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"camera": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Camera name to target, or '*' to target all cameras.",
|
||||||
|
},
|
||||||
|
"feature": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"detect",
|
||||||
|
"record",
|
||||||
|
"snapshots",
|
||||||
|
"audio",
|
||||||
|
"motion",
|
||||||
|
"enabled",
|
||||||
|
"birdseye",
|
||||||
|
"birdseye_mode",
|
||||||
|
"improve_contrast",
|
||||||
|
"ptz_autotracker",
|
||||||
|
"motion_contour_area",
|
||||||
|
"motion_threshold",
|
||||||
|
"notifications",
|
||||||
|
"audio_transcription",
|
||||||
|
"review_alerts",
|
||||||
|
"review_detections",
|
||||||
|
"object_descriptions",
|
||||||
|
"review_descriptions",
|
||||||
|
"profile",
|
||||||
|
],
|
||||||
|
"description": (
|
||||||
|
"The feature to change. Most features accept ON or OFF. "
|
||||||
|
"birdseye_mode accepts CONTINUOUS, MOTION, or OBJECTS. "
|
||||||
|
"motion_contour_area and motion_threshold accept a number. "
|
||||||
|
"profile accepts a profile name or 'none' to deactivate (requires camera='*')."
|
||||||
|
),
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The value to set. ON or OFF for toggles, a number for thresholds, a profile name or 'none' for profile.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": ["camera", "feature", "value"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "function",
|
"type": "function",
|
||||||
"function": {
|
"function": {
|
||||||
@ -255,6 +311,7 @@ async def _execute_search_objects(
|
|||||||
description="Execute a tool function call from an LLM.",
|
description="Execute a tool function call from an LLM.",
|
||||||
)
|
)
|
||||||
async def execute_tool(
|
async def execute_tool(
|
||||||
|
request: Request,
|
||||||
body: ToolExecuteRequest = Body(...),
|
body: ToolExecuteRequest = Body(...),
|
||||||
allowed_cameras: List[str] = Depends(get_allowed_cameras_for_filter),
|
allowed_cameras: List[str] = Depends(get_allowed_cameras_for_filter),
|
||||||
) -> JSONResponse:
|
) -> JSONResponse:
|
||||||
@ -272,6 +329,10 @@ async def execute_tool(
|
|||||||
if tool_name == "search_objects":
|
if tool_name == "search_objects":
|
||||||
return await _execute_search_objects(arguments, allowed_cameras)
|
return await _execute_search_objects(arguments, allowed_cameras)
|
||||||
|
|
||||||
|
if tool_name == "set_camera_state":
|
||||||
|
result = await _execute_set_camera_state(request, arguments)
|
||||||
|
return JSONResponse(content=result, status_code=200 if result.get("success") else 400)
|
||||||
|
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
content={
|
content={
|
||||||
"success": False,
|
"success": False,
|
||||||
@ -374,6 +435,48 @@ async def _get_live_frame_image_url(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def _execute_set_camera_state(
|
||||||
|
request: Request,
|
||||||
|
arguments: Dict[str, Any],
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
role = request.headers.get("remote-role", "")
|
||||||
|
if "admin" not in [r.strip() for r in role.split(",")]:
|
||||||
|
return {"error": "Admin privileges required to change camera settings."}
|
||||||
|
|
||||||
|
camera = arguments.get("camera", "").strip()
|
||||||
|
feature = arguments.get("feature", "").strip()
|
||||||
|
value = arguments.get("value", "").strip()
|
||||||
|
|
||||||
|
if not camera or not feature or not value:
|
||||||
|
return {"error": "camera, feature, and value are all required."}
|
||||||
|
|
||||||
|
from frigate.api.camera import _SUB_COMMAND_FEATURES
|
||||||
|
|
||||||
|
dispatcher = request.app.dispatcher
|
||||||
|
frigate_config = request.app.frigate_config
|
||||||
|
|
||||||
|
if feature == "profile":
|
||||||
|
if camera != "*":
|
||||||
|
return {"error": "Profile feature requires camera='*'."}
|
||||||
|
dispatcher._receive("profile/set", value)
|
||||||
|
return {"success": True, "camera": camera, "feature": feature, "value": value}
|
||||||
|
|
||||||
|
if feature not in dispatcher._camera_settings_handlers:
|
||||||
|
return {"error": f"Unknown feature: {feature}"}
|
||||||
|
|
||||||
|
if camera == "*":
|
||||||
|
cameras = list(frigate_config.cameras.keys())
|
||||||
|
elif camera not in frigate_config.cameras:
|
||||||
|
return {"error": f"Camera '{camera}' not found."}
|
||||||
|
else:
|
||||||
|
cameras = [camera]
|
||||||
|
|
||||||
|
for cam in cameras:
|
||||||
|
dispatcher._receive(f"{cam}/{feature}/set", value)
|
||||||
|
|
||||||
|
return {"success": True, "camera": camera, "feature": feature, "value": value}
|
||||||
|
|
||||||
|
|
||||||
async def _execute_tool_internal(
|
async def _execute_tool_internal(
|
||||||
tool_name: str,
|
tool_name: str,
|
||||||
arguments: Dict[str, Any],
|
arguments: Dict[str, Any],
|
||||||
@ -398,6 +501,8 @@ async def _execute_tool_internal(
|
|||||||
except (json.JSONDecodeError, AttributeError) as e:
|
except (json.JSONDecodeError, AttributeError) as e:
|
||||||
logger.warning(f"Failed to extract tool result: {e}")
|
logger.warning(f"Failed to extract tool result: {e}")
|
||||||
return {"error": "Failed to parse tool result"}
|
return {"error": "Failed to parse tool result"}
|
||||||
|
elif tool_name == "set_camera_state":
|
||||||
|
return await _execute_set_camera_state(request, arguments)
|
||||||
elif tool_name == "get_live_context":
|
elif tool_name == "get_live_context":
|
||||||
camera = arguments.get("camera")
|
camera = arguments.get("camera")
|
||||||
if not camera:
|
if not camera:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user