Compare commits

...

3 Commits

Author SHA1 Message Date
074ff8bbb4 Merge pull request 'Made improvements in AI Agent's tool get_forecast_weather' (#8) from dev into master
Reviewed-on: #8
Reviewed-by: AllfatherHatt <allfatherhatt@noreply.localhost>
2025-06-18 17:13:22 +02:00
4e22274f9b - Removed unused debug import 2025-06-18 20:10:05 +05:00
a5ed9f9e1c Applied changes made in GitHub 2025-06-17 10:57:19 +05:00
3 changed files with 39 additions and 26 deletions

View File

@ -1,10 +1,11 @@
import random import random
import json import json
import asyncio
from os import environ
import openai import openai
from openai import OpenAIError from openai import OpenAIError
from .weather import time_now, get_current_weather, get_weather_forecast from weather import time_now, get_current_weather, get_weather_forecast
from .tools_description import TOOLS from tools_description import TOOLS
from .debug_stuff import debug
CALLABLE_FUNCTIONS = { CALLABLE_FUNCTIONS = {
# Dictionary with functions to call. # Dictionary with functions to call.
@ -21,15 +22,13 @@ class Completion:
self.__api_key = api_key self.__api_key = api_key
self.__messages = [] self.__messages = []
@debug async def create_completion(self):
async def create_completion(self, messages: list):
self.__messages = messages
model = self.__model model = self.__model
try: try:
client = openai.AsyncClient(api_key=self.__api_key) client = openai.AsyncClient(api_key=self.__api_key)
completion_kwargs = { completion_kwargs = {
"model": model, "model": model,
"messages": messages, "messages": self.__messages,
"max_tokens": 4096, "max_tokens": 4096,
"temperature": 0.7, "temperature": 0.7,
"presence_penalty": 0.5, "presence_penalty": 0.5,
@ -47,7 +46,7 @@ class Completion:
func_args = json.loads(i_call.function.arguments) func_args = json.loads(i_call.function.arguments)
tool_call_id = i_call.id tool_call_id = i_call.id
self.function_manager(func_name, func_args, tool_call_id) self.function_manager(func_name, func_args, tool_call_id)
return self.create_completion(messages=self.__messages) return await self.create_completion()
return response_content return response_content
except OpenAIError as e: except OpenAIError as e:
return self.get_error_message(error_message=str(e), error_type="OpenAIError") return self.get_error_message(error_message=str(e), error_type="OpenAIError")
@ -81,3 +80,14 @@ class Completion:
result = CALLABLE_FUNCTIONS[func_name](**func_kwargs) result = CALLABLE_FUNCTIONS[func_name](**func_kwargs)
self.append_message(role="tool", content=result, tool_call_id=tool_call_id) self.append_message(role="tool", content=result, tool_call_id=tool_call_id)
if __name__ == '__main__':
async def main():
test_message = input('Your input: ')
completion = Completion(model='gpt-4.1-mini', api_key=environ.get('OPENAI_API_KEY'))
completion.append_message(role='user', content=test_message)
result = await completion.create_completion()
print(result)
asyncio.run(main())

View File

@ -1,11 +1,17 @@
TOOLS = [ TOOLS = [
# time_now
{ {
'type': 'function', 'type': 'function',
'function': { 'function': {
'name': 'time_now', 'name': 'time_now',
'description': 'Get current date and time in UTC timezone.', 'description': '''
Get current date and time in UTC timezone.
Use this before get_weather_forecast function if user gave you date of forecast
instead of number of days.
''',
} }
}, },
# get_current_weather
{ {
'type': 'function', 'type': 'function',
'function': { 'function': {
@ -32,6 +38,7 @@ TOOLS = [
'strict': True 'strict': True
} }
}, },
# get_weather_forecast
{ {
'type': 'function', 'type': 'function',
'function': { 'function': {
@ -41,7 +48,8 @@ TOOLS = [
forecast and weather alert as json. The data is returned as a Forecast Object. forecast and weather alert as json. The data is returned as a Forecast Object.
Forecast object contains astronomy data, day weather forecast and hourly interval weather information Forecast object contains astronomy data, day weather forecast and hourly interval weather information
for a given city. for a given city.
With a free weather API subscription, only up to three days of forecast can be requested. Number of days could be less, depending on the API subscription plan.
With a free plan only up to three days of forecast would be returned.
''', ''',
'parameters': { 'parameters': {
'type': 'object', 'type': 'object',
@ -53,16 +61,15 @@ TOOLS = [
e.g: "Copenhagen", or "Copenhagen, Louisiana, US", if needed specifying. e.g: "Copenhagen", or "Copenhagen, Louisiana, US", if needed specifying.
''' '''
}, },
'dt': { 'days': {
'type': 'string', 'type': 'integer',
'description': ''' 'description': '''
The date up until to request the forecast in YYYY-MM-DD format. Number of days of forecast between 0 and 13, where 0 is only today, 1 up to tomorrow, etc.
Check the **time_now** function first if you unsure which date it is.
''' '''
}, },
}, },
'required': [ 'required': [
'location', 'dt' 'location', 'days'
], ],
'additionalProperties': False 'additionalProperties': False
}, },

View File

@ -2,27 +2,26 @@ from datetime import datetime, timezone
from os import environ from os import environ
import requests import requests
import json import json
from .debug_stuff import debug
#WEATHER_API_KEY = environ.get('WEATHER_API_KEY') #WEATHER_API_KEY = environ.get('WEATHER_API_KEY')
URL = 'http://api.weatherapi.com/v1' URL = 'http://api.weatherapi.com/v1'
@debug
def time_now() -> str: def time_now() -> str:
return str(datetime.now(timezone.utc)) return str(datetime.now(timezone.utc))
@debug
def get_current_weather(location: str) -> str: def get_current_weather(location: str) -> str:
weather = Weather(location=location) weather = Weather(location=location)
return json.dumps(weather.realtime()) return json.dumps(weather.realtime())
@debug def get_weather_forecast(location: str, days: int = None) -> str:
def get_weather_forecast(location: str, days: int = 14, dt: str = '2025-03-24') -> str: days += 1
days = max(1, days)
days = min(14, days)
weather = Weather(location=location) weather = Weather(location=location)
return json.dumps(weather.forecast(days=days, dt=dt)) return json.dumps(weather.forecast(days=days))
class Weather: class Weather:
@ -39,7 +38,6 @@ class Weather:
response = requests.get(url=f'{URL}{method}', params=params) response = requests.get(url=f'{URL}{method}', params=params)
return response.json() return response.json()
@debug
def realtime(self): def realtime(self):
method = '/current.json' method = '/current.json'
params = { params = {
@ -48,19 +46,17 @@ class Weather:
} }
return self.make_request(method=method, params=params) return self.make_request(method=method, params=params)
@debug def forecast(self, days: int = 14):
def forecast(self, days: int = 14, dt: str = '2025-03-24'):
method = '/forecast.json' method = '/forecast.json'
params = { params = {
'key': self.api_key, 'key': self.api_key,
'q': self.location, 'q': self.location,
'days': days, 'days': days,
'dt': dt,
} }
return self.make_request(method=method, params=params) return self.make_request(method=method, params=params)
if __name__ == '__main__': if __name__ == '__main__':
test_weather = Weather('Aqtobe') test_weather = Weather('Aqtobe')
result = json.dumps(test_weather.forecast(days=14, dt='2025-03-24'), indent=2) result = json.dumps(test_weather.forecast(days=13), indent=2)
print(result) print(result)