from langchain.tools import tool from datetime import datetime, timedelta from re import search from dataclasses import dataclass from typing import Union import logging from langchain_core.tools import Tool from langchain_experimental.utilities import PythonREPL @tool def add(a: float, b: float) -> str: """Adds a+b and returns the sum""" af = float(a) bf = float(b) return f"{af} + {af} = {af+bf}" @tool def multiply(a: float, b: float) -> str: """Multiplies a*b and returns the product""" af = float(a) bf = float(b) return f"{af} * {bf} = {af*bf}" @tool def get_current_date_and_time() -> str: """Return current Date and time""" return "Thursday the 8th of August 2024 18:03" @dataclass class Entry: time: datetime content: str note_entries = [ Entry( time=datetime.strptime("2024/08/03 14:58", "%Y/%m/%d %H:%M"), content="Granny Petra says I should call Wolfgang to ask him when Susanne comes back when he comes back from his holidays." ), Entry( time=datetime.strptime("2024/08/07 09:15", "%Y/%m/%d %H:%M"), content="Mom says to buy some fresh flowers for the living room before Aunt Linda visits." ), Entry( time=datetime.strptime("2024/08/06 18:30", "%Y/%m/%d %H:%M"), content="Pick up the dry cleaning on Thursday; they close early on Fridays." ), Entry( time=datetime.strptime("2024/08/05 11:45", "%Y/%m/%d %H:%M"), content="Ask Dr. Mills about the side effects of the new medication he got me." ), Entry( time=datetime.strptime("2024/08/04 16:00", "%Y/%m/%d %H:%M"), content="Call the plumber to fix the leak in the upstairs bathroom." ), Entry( time=datetime.strptime("2024/08/03 08:00", "%Y/%m/%d %H:%M"), content="Schedule a car service appointment before the road trip to the mountains." ), Entry( time=datetime.strptime("2024/08/02 20:10", "%Y/%m/%d %H:%M"), content="Check if the library has a copy of the new mystery novel everyone is talking about." ), Entry( time=datetime.strptime("2024/08/01 14:30", "%Y/%m/%d %H:%M"), content="Send a thank-you note to Mrs. Jenkins for the lovely dinner last weekend." ), Entry( time=datetime.strptime("2024/07/31 12:05", "%Y/%m/%d %H:%M"), content="Email the project update to the team by the end of the week." ), Entry( time=datetime.strptime("2024/07/30 07:50", "%Y/%m/%d %H:%M"), content="Pick up a birthday card for Uncle George before the family gathering on Sunday." ), Entry( time=datetime.strptime("2024/07/29 15:20", "%Y/%m/%d %H:%M"), content="Research local yoga classes; consider signing up for the weekend session." ), Entry( time=datetime.strptime("2023/08/01 07:21", "%Y/%m/%d %H:%M"), content="Talk to Joffrey for the insurance!" ), Entry( time=datetime.strptime("2023/08/01 23:10", "%Y/%m/%d %H:%M"), content="Went out with Charlotte for our anniversary. Pizza at Cavalinos. She loved the Necklace!" ) ] @tool def get_notes_in_timespan(begin: str, to: str) -> str: """Recieves the Notes saved in a time span. aguments: begin: str # start of the time span (incluive) %Y/%m/%d to: str # end of the timespan (incluive) %Y/%m/%d exaples: {"begin": "2012/08/31", "to": "2012/09/06"} # 7 days from the 31st 00:00 till the 6th 23:59 {"begin": "2019/04/14", "to": "2019/04/14"} # All notes from the 19th of April 2019""" try: begin_d = datetime.strptime(begin, "%Y/%m/%d") to_d = datetime.strptime(to+" 23:59", "%Y/%m/%d %H:%M") except ValueError: return "Error: Invalid input. Date format is %Y/%m/%d" try: assert begin_d < to_d except AssertionError: return "Error: from time has to be before to time." filtered_entries = [entry for entry in note_entries if begin_d <= entry.time <= to_d] if filtered_entries == []: return "No entries were found for that time period." ret = "" is_first = True for entry in filtered_entries: ret += '' if is_first else '\n\n' ret += f"{datetime.strftime(entry.time, '%Y/%m/%d %H:%M')} {entry.content}" is_first = False return ret @tool def get_notes_containing(patterns: Union[list[str], str]) -> str: """Recieves the Notes matching any of the RegEx patterns. aguments: patterns: Union[list[str], str] # case insensitive pattern(s) notes are to be mached against exaples: {"patterns": [ "Aunt(ie)?", "Sabine" ]} # Looks for Notes related to Aunt Sabine""" if isinstance(patterns, list): big_pattern = '|'.join(f"({s})" for s in patterns) elif isinstance(patterns, str): big_pattern = patterns else: return f"Error: Invalid Input type. `patterns` can either be a list of strings or a single string. But got {type(patterns)}." filtered_entries = [entry for entry in note_entries if search(big_pattern.lower(), entry.content.lower())] ret = "" is_first = True for entry in filtered_entries: ret += '' if is_first else '\n\n' ret += f"{datetime.strftime(entry.time, '%Y/%m/%d %H:%M')} {entry.content}" is_first = False if ret == "": ret = "No matching notes were found. Try diffrent patterns." return ret @tool def write_note(command: str) -> str: """Write a not with the current time to the database.""" return command @tool def save_python_repl(command: str): """Simulates the normal python repl but with certain patterns blocked for savety reasons""" python_repl = PythonREPL() blocked_patterns = [ "^ *os\\.", "import os", "^ *subprocess\\.", "^ *(with)? ?open\\(", "^ *shutil\\.", ] valid = True for pattern in blocked_patterns: if search(pattern, command): valid = False break if valid: ret = python_repl.run(command) if ret == "": ret = python_repl.run(f'print(({command}), end="")') return ret else: return f"Command not executed, becaise the blocked pattern `{pattern}` was found in the command."