feat: ✨ Working tool calls
o new file: llm_interface.py
This commit is contained in:
@@ -3,56 +3,28 @@ import openmeteo_requests
|
||||
import requests_cache
|
||||
from retry_requests import retry
|
||||
import json
|
||||
|
||||
# WMO Weather interpretation codes mapping
|
||||
WEATHER_CODE_MAP = {
|
||||
0: "Clear sky",
|
||||
1: "Mainly clear",
|
||||
2: "Partly cloudy",
|
||||
3: "Overcast",
|
||||
45: "Fog",
|
||||
48: "Depositing rime fog",
|
||||
51: "Light drizzle",
|
||||
53: "Moderate drizzle",
|
||||
55: "Dense drizzle",
|
||||
56: "Light freezing drizzle",
|
||||
57: "Dense freezing drizzle",
|
||||
61: "Slight rain",
|
||||
63: "Moderate rain",
|
||||
65: "Heavy rain",
|
||||
66: "Light freezing rain",
|
||||
67: "Heavy freezing rain",
|
||||
71: "Slight snow",
|
||||
73: "Moderate snow",
|
||||
75: "Heavy snow",
|
||||
77: "Snow grains",
|
||||
80: "Slight rain showers",
|
||||
81: "Moderate rain showers",
|
||||
82: "Violent rain showers",
|
||||
85: "Slight snow showers",
|
||||
86: "Heavy snow showers",
|
||||
95: "Thunderstorm",
|
||||
96: "Thunderstorm with slight hail",
|
||||
99: "Thunderstorm with heavy hail"
|
||||
}
|
||||
import config
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
class ToolExecutor:
|
||||
def __init__(self):
|
||||
def __init__(self, logger):
|
||||
self.tools = {
|
||||
"get_weather": self.get_weather
|
||||
"get_weather": self.get_weather,
|
||||
"find_folder": self.find_folder
|
||||
}
|
||||
|
||||
def process_llm_response(self, llm_output):
|
||||
|
||||
# Parse the tool call from LLM response
|
||||
if llm_output.startswith('{"tool":'):
|
||||
self.logger = logger
|
||||
|
||||
def process_llm_response(self, llm_output):
|
||||
if llm_output.startswith('{"tool":'):
|
||||
# Parse the tool call from LLM response
|
||||
llm_output = json.loads(llm_output)
|
||||
|
||||
print(llm_output)
|
||||
self.logger.info(f"Parsed LLM output: {llm_output}")
|
||||
tool_name = llm_output.get("tool",'no tool')
|
||||
parameters = llm_output.get("parameters", 'no parameters')
|
||||
print(f'parsed tool: {tool_name}, parsed parameters: {parameters}')
|
||||
self.logger.info(f'parsed tool: {tool_name}, parsed parameters: {parameters}')
|
||||
|
||||
# Execute the actual function
|
||||
result = self.tools[tool_name](**parameters)
|
||||
@@ -64,7 +36,7 @@ class ToolExecutor:
|
||||
def get_weather(self, city: str, units: str = "celsius"):
|
||||
"""Get current weather for a location using Open-Meteo API with openmeteo-requests library."""
|
||||
|
||||
print(f'get weather called, city = {city}')
|
||||
self.logger.info(f'get weather called, city = {city}')
|
||||
if not city:
|
||||
raise ValueError("City parameter is required")
|
||||
|
||||
@@ -86,7 +58,7 @@ class ToolExecutor:
|
||||
geo_response = requests.get(geocoding_url, params=geocoding_params, timeout=10)
|
||||
geo_response.raise_for_status()
|
||||
geo_data = geo_response.json()
|
||||
print(f'Geo data for city: {geo_data}')
|
||||
self.logger.info(f'Geo data for city: {geo_data}')
|
||||
|
||||
if not geo_data.get("results"):
|
||||
raise Exception(f"City '{city}' not found")
|
||||
@@ -119,11 +91,11 @@ class ToolExecutor:
|
||||
|
||||
responses = openmeteo.weather_api(url, params=params)
|
||||
response = responses[0]
|
||||
print(f'Weather API response: {response}')
|
||||
self.logger.info(f'Weather API response: {response}')
|
||||
|
||||
# Get current weather data
|
||||
current = response.Current()
|
||||
print(f'Current weather data: {current}')
|
||||
self.logger.info(f'Current weather data: {current}')
|
||||
|
||||
# Extract values using the library's methods
|
||||
temperature = current.Variables(0).Value() # temperature_2m
|
||||
@@ -132,7 +104,7 @@ class ToolExecutor:
|
||||
pressure = current.Variables(3).Value() # surface_pressure
|
||||
wind_speed = current.Variables(4).Value() # wind_speed_10m
|
||||
|
||||
condition = WEATHER_CODE_MAP.get(weather_code, "Unknown")
|
||||
condition = config.WEATHER_CODE_MAP.get(weather_code, "Unknown")
|
||||
|
||||
|
||||
json_reply = {
|
||||
@@ -146,8 +118,43 @@ class ToolExecutor:
|
||||
"country": country,
|
||||
"coordinates": {"latitude": latitude, "longitude": longitude}
|
||||
}
|
||||
print(json_reply)
|
||||
self.logger.info(f"Weather data result: {json_reply}")
|
||||
return json_reply
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"Weather lookup failed: {str(e)}")
|
||||
raise Exception(f"Weather lookup failed: {str(e)}")
|
||||
|
||||
def find_folder(self, folder_name: str, search_path: str = "/home/"):
|
||||
"""Search for folders with a specific name on the PC."""
|
||||
|
||||
self.logger.info(f'find_folder called, folder_name = {folder_name}, search_path = {search_path}')
|
||||
|
||||
if not folder_name:
|
||||
raise ValueError("folder_name parameter is required")
|
||||
|
||||
try:
|
||||
found_folders = []
|
||||
# Use find command to search for directories
|
||||
cmd = ['find', search_path, '-type', 'd', '-name', folder_name]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
self.logger.warning(result)
|
||||
if result.stdout:
|
||||
found_folders = [path.strip() for path in result.stdout.split('\n') if path.strip()]
|
||||
|
||||
# Limit results to first 50 to avoid overwhelming output
|
||||
found_folders = found_folders[:50]
|
||||
|
||||
json_reply = {
|
||||
"folder_name": folder_name,
|
||||
"search_path": search_path,
|
||||
"found_folders": found_folders,
|
||||
"count": len(found_folders)
|
||||
}
|
||||
|
||||
self.logger.info(f"Folder search result: {json_reply}")
|
||||
return json_reply
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
raise Exception("Folder search timed out after 30 seconds")
|
||||
except Exception as e:
|
||||
raise Exception(f"Folder search failed: {str(e)}")
|
||||
Reference in New Issue
Block a user