enhanced functions

This commit is contained in:
Saifeddine ALOUI 2024-06-09 23:20:17 +02:00
parent a52db1fb9f
commit 7da874228b
15 changed files with 646 additions and 127 deletions

View File

@ -0,0 +1,7 @@
from lollms.functions.analyze_code.create_project_database import create_project_database, create_project_database_function
from lollms.functions.analyze_code.retreive_information_for_task import retrieve_information_for_task, retrieve_information_for_task_function
from lollms.functions.analyze_code.retrieve_classes_from_project import retrieve_classes_from_project, retrieve_classes_from_project_function
from lollms.functions.analyze_code.update_class_in_file import update_class_in_file, update_class_in_file_function
from lollms.functions.analyze_code.update_function_in_file import update_function_in_file, update_function_in_file_function
from lollms.functions.analyze_code.add_function_to_file import add_function_to_file, add_function_to_file_function

View File

@ -0,0 +1,58 @@
# Lollms function call definition file
from functools import partial
from lollms.utilities import PackageManager
from ascii_colors import trace_exception
from typing import List, Union
from pathlib import Path
import ast
def add_function_to_file(file_path: Union[str, Path], function_name: str, function_content: str) -> str:
"""
Adds a new function to the specified file.
Args:
file_path (Union[str, Path]): The path to the Python file.
function_name (str): The name of the function to add.
function_content (str): The content of the function to add.
Returns:
str: Success message or error message.
"""
try:
file_path = Path(file_path)
# Validate the file path
if not file_path.exists() or not file_path.is_file():
return "Invalid file path."
with open(file_path, "r", encoding="utf-8") as file:
content = file.read()
tree = ast.parse(content)
# Check if function already exists
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef) and node.name == function_name:
return f"Function {function_name} already exists in the file."
# Add the new function content at the end of the file
with open(file_path, "a", encoding="utf-8") as file:
file.write("\n\n" + function_content)
return f"Function {function_name} added successfully to file {file_path}."
except Exception as e:
return trace_exception(e)
# Metadata function
def add_function_to_file_function():
return {
"function_name": "add_function_to_file", # The function name in string
"function": add_function_to_file, # The function to be called
"function_description": "Adds a new function to the specified file.", # Description of the function
"function_parameters": [ # The set of parameters
{"name": "file_path", "type": "str"},
{"name": "function_name", "type": "str"},
{"name": "function_content", "type": "str"},
]
}

View File

@ -1,4 +1,8 @@
# Lollms function call definition file
"""
"""
from functools import partial
from typing import List, Dict, Union, Any
from lollms.utilities import PackageManager
@ -129,102 +133,4 @@ def create_project_database_function(project_path, llm):
"function": partial(create_project_database,project_path=project_path, llm=llm),
"function_description": "Creates a database containing structured information about a Python project.",
"function_parameters": []
}
# Lollms function call definition file
from functools import partial
from typing import List, Dict
from lollms.utilities import PackageManager
from ascii_colors import trace_exception
from pathlib import Path
import sqlite3
# Ensure required packages are installed
if not PackageManager.check_package_installed("sqlite3"):
PackageManager.install_package("sqlite3")
def retrieve_information_for_task(project_path: str, task_description: str, llm: APScript) -> Union[str, Dict[str, str]]:
"""
Retrieves information from the database to perform a task given by the user.
Args:
project_path (str): The path to the project directory.
task_description (str): The description of the task to perform.
llm (APScript): The language model instance for generating SQL queries.
Returns:
Union[str, Dict[str, str]]: A string containing relevant information or an error message.
"""
try:
db_path = Path(project_path) / "project_info.db"
# Validate the database path
if not db_path.exists() or not db_path.is_file():
return "Invalid database path."
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Retrieve the list of classes and their descriptions
cursor.execute("SELECT name, docstring FROM classes")
classes = cursor.fetchall()
# Format the classes into a string
classes_text = "\n".join([f"Class: {cls[0]}, Description: {cls[1]}" for cls in classes])
# Ask the LLM which classes are needed for the task
prompt = f"{llm.personality.config.start_header_id_template}{llm.personality.config.system_message_template}{llm.personality.config.end_header_id_template}" \
f"Given the following list of classes and their descriptions:\n" \
f"{classes_text}\n\n" \
f"Task description: {task_description}\n\n" \
f"{llm.personality.config.start_header_id_template}instructions{llm.personality.config.end_header_id_template}" \
f"Which classes are needed to perform the task? List the class names.\n" \
f"Answer in form of a json list inside a json markdown tag.\n" \
f"{llm.personality.config.start_header_id_template}assistant{llm.personality.config.end_header_id_template}"
needed_classes = llm.fast_gen(prompt, callback=llm.sink).strip()
needed_classes = llm.extract_code_blocks(needed_classes)
if len(needed_classes)>0:
needed_classes = json.loads(needed_classes[0]["content"])
# Retrieve the relevant information for the needed classes
class_info = {}
for class_name in needed_classes:
cursor.execute("SELECT * FROM classes WHERE name = ?", (class_name,))
class_info[class_name] = cursor.fetchone()
# Retrieve the project description and structure
cursor.execute("SELECT name, description FROM project_info")
project_info = cursor.fetchone()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
tables = cursor.fetchall()
conn.close()
# Format the results into a string
result_text = f"Project Name: {project_info[0]}\nProject Description: {project_info[1]}\n\n"
result_text += "Project Structure:\n" + "\n".join([table[0] for table in tables]) + "\n\n"
result_text += "Needed Classes Information:\n"
for class_name, info in class_info.items():
result_text += f"Class: {class_name}\n"
result_text += f"Description: {info[2]}\n"
result_text += f"Methods: {info[4]}\n"
result_text += f"Static Methods: {info[5]}\n\n"
return result_text.strip()
else:
return "Failed to ask the llm"
except Exception as e:
return str(e)
def retrieve_information_for_task_function(project_path, llm):
return {
"function_name": "retrieve_information_for_task",
"function": partial(retrieve_information_for_task, project_path=project_path, llm=llm),
"function_description": "Retrieves information from the database to perform a task given by the user.",
"function_parameters": [
{"name": "task_description", "type": "str", "description":"a description of "}
]
}
}

View File

@ -0,0 +1,96 @@
# Lollms function call definition file
from functools import partial
from typing import List, Dict, Union
from lollms.utilities import PackageManager
from lollms.personality import APScript
from ascii_colors import trace_exception
from pathlib import Path
import sqlite3
import json
# Ensure required packages are installed
if not PackageManager.check_package_installed("sqlite3"):
PackageManager.install_package("sqlite3")
def retrieve_information_for_task(project_path: str, task_description: str, llm: APScript) -> Union[str, Dict[str, str]]:
"""
Retrieves information from the database to perform a task given by the user.
Args:
project_path (str): The path to the project directory.
task_description (str): The description of the task to perform.
llm (APScript): The language model instance for generating SQL queries.
Returns:
Union[str, Dict[str, str]]: A string containing relevant information or an error message.
"""
try:
db_path = Path(project_path) / "project_info.db"
# Validate the database path
if not db_path.exists() or not db_path.is_file():
return "Invalid database path."
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Retrieve the list of classes and their descriptions
cursor.execute("SELECT name, docstring FROM classes")
classes = cursor.fetchall()
# Format the classes into a string
classes_text = "\n".join([f"Class: {cls[0]}, Description: {cls[1]}" for cls in classes])
# Ask the LLM which classes are needed for the task
prompt = f"{llm.personality.config.start_header_id_template}{llm.personality.config.system_message_template}{llm.personality.config.end_header_id_template}" \
f"Given the following list of classes and their descriptions:\n" \
f"{classes_text}\n\n" \
f"Task description: {task_description}\n\n" \
f"{llm.personality.config.start_header_id_template}instructions{llm.personality.config.end_header_id_template}" \
f"Which classes are needed to perform the task? List the class names.\n" \
f"Answer in form of a json list inside a json markdown tag.\n" \
f"{llm.personality.config.start_header_id_template}assistant{llm.personality.config.end_header_id_template}"
needed_classes = llm.fast_gen(prompt, callback=llm.sink).strip()
needed_classes = llm.extract_code_blocks(needed_classes)
if len(needed_classes)>0:
needed_classes = json.loads(needed_classes[0]["content"])
# Retrieve the relevant information for the needed classes
class_info = {}
for class_name in needed_classes:
cursor.execute("SELECT * FROM classes WHERE name = ?", (class_name,))
class_info[class_name] = cursor.fetchone()
# Retrieve the project description and structure
cursor.execute("SELECT name, description FROM project_info")
project_info = cursor.fetchone()
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
tables = cursor.fetchall()
conn.close()
# Format the results into a string
result_text = f"Project Name: {project_info[0]}\nProject Description: {project_info[1]}\n\n"
result_text += "Project Structure:\n" + "\n".join([table[0] for table in tables]) + "\n\n"
result_text += "Needed Classes Information:\n"
for class_name, info in class_info.items():
result_text += f"Class: {class_name}\n"
result_text += f"Description: {info[2]}\n"
result_text += f"Methods: {info[4]}\n"
result_text += f"Static Methods: {info[5]}\n\n"
return result_text.strip()
else:
return "Failed to ask the llm"
except Exception as e:
return str(e)
def retrieve_information_for_task_function(project_path, llm):
return {
"function_name": "retrieve_information_for_task",
"function": partial(retrieve_information_for_task, project_path=project_path, llm=llm),
"function_description": "Retrieves information from the database to perform a task given by the user.",
"function_parameters": [
{"name": "task_description", "type": "str", "description":"a description of "}
]
}

View File

@ -0,0 +1,59 @@
# Import necessary libraries
from pathlib import Path
from functools import partial
from typing import List, Union
import ast
# ascii_colors offers advanced console coloring and bug tracing
from ascii_colors import trace_exception
# Function to retrieve classes from the project files
def retrieve_classes_from_project(class_names: List[str], project_path: Union[str, Path]) -> str:
"""
Retrieves the code of specified classes from the given project path.
Args:
project_path (Union[str, Path]): The path to the Python project directory.
class_names (List[str]): List of class names to retrieve.
Returns:
str: The code of the specified classes as a string.
"""
try:
project_path = Path(project_path)
# Validate the project path
if not project_path.exists() or not project_path.is_dir():
return "Invalid project path."
class_code = "\n"
# Traverse the project directory and extract class code
for py_file in project_path.rglob("*.py"):
with open(py_file, "r", encoding="utf-8") as file:
content = file.read()
tree = ast.parse(content)
for node in ast.walk(tree):
if isinstance(node, ast.ClassDef) and node.name in class_names:
class_code += f"\n\n# Class: {node.name} in file: {py_file.relative_to(project_path)}\n"
class_code += "```python\n"
class_code += "\n".join(content.split("\n")[node.lineno-1:node.end_lineno])
class_code += "\n```\n"
return class_code if class_code else "No specified classes found."
except Exception as e:
return trace_exception(e)
# Metadata function
def retrieve_classes_from_project_function(project_path:str):
return {
"function_name": "retrieve_classes_from_project",
"function": partial(retrieve_classes_from_project,project_path = project_path),
"function_description": "Retrieves the code of specified classes from the given project path.",
"function_parameters": [
{"name": "class_names", "type": "list", "description": "List of class names to retrieve."}
]
}

View File

@ -0,0 +1,85 @@
# Lollms function call definition file
from functools import partial
from lollms.utilities import PackageManager
from ascii_colors import trace_exception
from typing import List, Union
from pathlib import Path
import ast
def update_class_in_file(class_name: str, new_content: str, method_name: Union[str, None] = None, project_path: Union[str, Path] = "") -> str:
"""
Updates the specified class or method with new content in the given project path.
Args:
class_name (str): The name of the class to update.
new_content (str): The new content to replace the class or method with.
method_name (Union[str, None]): The name of the method to update. If None, updates the entire class.
project_path (Union[str, Path]): The path to the Python project directory.
Returns:
str: Success message or error message.
"""
try:
project_path = Path(project_path)
# Validate the project path
if not project_path.exists() or not project_path.is_dir():
return "Invalid project path."
# Traverse the project directory and update class or method content
for py_file in project_path.rglob("*.py"):
with open(py_file, "r", encoding="utf-8") as file:
content = file.read()
tree = ast.parse(content)
class_found = False
method_found = False
updated_content = []
lines = content.split("\n")
for node in ast.walk(tree):
if isinstance(node, ast.ClassDef) and node.name == class_name:
class_found = True
if method_name is None:
# Update entire class content
updated_content.extend(lines[:node.lineno-1])
updated_content.append(new_content)
updated_content.extend(lines[node.end_lineno:])
else:
# Update specific method content
for class_node in node.body:
if isinstance(class_node, ast.FunctionDef) and class_node.name == method_name:
method_found = True
# Calculate the indentation level
indent_level = len(lines[class_node.lineno-1]) - len(lines[class_node.lineno-1].lstrip())
indented_new_content = "\n".join(" " * indent_level + line for line in new_content.split("\n"))
updated_content.extend(lines[:class_node.lineno-1])
updated_content.append(indented_new_content)
updated_content.extend(lines[class_node.end_lineno:])
break
if not method_found:
return f"Method {method_name} not found in class {class_name}."
break
if class_found:
with open(py_file, "w", encoding="utf-8") as file:
file.write("\n".join(updated_content))
return f"{'Method ' + method_name if method_name else 'Class ' + class_name} updated successfully in file {py_file.relative_to(project_path)}."
return "Class not found in the specified project."
except Exception as e:
return trace_exception(e)
# Metadata function
def update_class_in_file_function(project_path:str ):
return {
"function_name": "update_class_in_file", # The function name in string
"function": partial(update_class_in_file,project_path = project_path), # The function to be called
"function_description": "Updates the specified class with new content in the given project path.", # Description of the function
"function_parameters": [ # The set of parameters
{"name": "class_name", "type": "str"},
{"name": "new_content", "type": "str"},
{"name": "method_name", "type": "str", "description":"An optional method name, required only if you need to change a single method content. If you need to change the whole class, do not set this element"},
]
}

View File

@ -0,0 +1,70 @@
# Lollms function call definition file
from functools import partial
from lollms.utilities import PackageManager
from ascii_colors import trace_exception
from typing import List, Union
from pathlib import Path
import ast
def update_function_in_file(function_name: str, new_content: str, project_path: Union[str, Path] = "") -> str:
"""
Updates the specified function with new content in the given project path.
Args:
function_name (str): The name of the function to update.
new_content (str): The new content to replace the function with.
project_path (Union[str, Path]): The path to the Python project directory.
Returns:
str: Success message or error message.
"""
try:
project_path = Path(project_path)
# Validate the project path
if not project_path.exists() or not project_path.is_dir():
return "Invalid project path."
# Traverse the project directory and update function content
for py_file in project_path.rglob("*.py"):
with open(py_file, "r", encoding="utf-8") as file:
content = file.read()
tree = ast.parse(content)
function_found = False
updated_content = []
lines = content.split("\n")
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef) and node.name == function_name:
function_found = True
# Calculate the indentation level
indent_level = len(lines[node.lineno-1]) - len(lines[node.lineno-1].lstrip())
indented_new_content = "\n".join(" " * indent_level + line for line in new_content.split("\n"))
updated_content.extend(lines[:node.lineno-1])
updated_content.append(indented_new_content)
updated_content.extend(lines[node.end_lineno:])
break
if function_found:
with open(py_file, "w", encoding="utf-8") as file:
file.write("\n".join(updated_content))
return f"Function {function_name} updated successfully in file {py_file.relative_to(project_path)}."
return "Function not found in the specified project."
except Exception as e:
return trace_exception(e)
# Metadata function
def update_function_in_file_function(project_path:str ):
return {
"function_name": "update_function_in_file", # The function name in string
"function": partial(update_function_in_file, project_path=project_path), # The function to be called
"function_description": "Updates the specified function with new content in the given project path.", # Description of the function
"function_parameters": [ # The set of parameters
{"name": "function_name", "type": "str"},
{"name": "new_content", "type": "str"},
]
}

View File

@ -0,0 +1,75 @@
# Lollms function call definition file
# File Name: draw_bounding_boxes.py
# Author: Saif (ParisNeo)
# Description: This script defines a function that takes an image file path and a list of bounding boxes in the form of x, y, w, h in normalized mode along with the labels, and returns the bounding boxes placed on top of the images with the labels.
# Lollms function call definition file
from functools import partial
from typing import List, Tuple
from lollms.utilities import PackageManager
from ascii_colors import trace_exception
from pathlib import Path
# Ensure necessary packages are installed
if not PackageManager.check_package_installed("Pillow"):
PackageManager.install_package("Pillow")
from PIL import Image, ImageDraw, ImageFont
def draw_bounding_boxes(image_path: str, bounding_boxes: List[Tuple[float, float, float, float, str]]) -> str:
"""
Draws bounding boxes on an image and saves the result.
Args:
image_path (str): Path to the input image file.
bounding_boxes (List[Tuple[float, float, float, float, str]]): List of bounding boxes in normalized coordinates (x, y, w, h) along with labels.
Returns:
str: Path to the output image file with bounding boxes drawn.
"""
try:
image_path = Path(image_path)
if not image_path.exists():
raise FileNotFoundError(f"Image file not found: {image_path}")
# Load the image
image = Image.open(image_path)
draw = ImageDraw.Draw(image)
width, height = image.size
# Iterate over bounding boxes and draw them
for bbox in bounding_boxes:
x, y, w, h, label = bbox
left = x * width
top = y * height
right = left + (w * width)
bottom = top + (h * height)
# Draw rectangle
draw.rectangle([left, top, right, bottom], outline="red", width=2)
# Draw label
font = ImageFont.load_default()
text_size = draw.textsize(label, font=font)
text_background = [left, top - text_size[1], left + text_size[0], top]
draw.rectangle(text_background, fill="red")
draw.text((left, top - text_size[1]), label, fill="white", font=font)
# Save the output image
output_path = image_path.with_name(f"{image_path.stem}_with_boxes{image_path.suffix}")
image.save(output_path)
return str(output_path)
except Exception as e:
return trace_exception(e)
def draw_bounding_boxes_function():
return {
"function_name": "draw_bounding_boxes",
"function": draw_bounding_boxes,
"function_description": "Draws bounding boxes on an image and saves the result.",
"function_parameters": [
{"name": "image_path", "type": "str"},
{"name": "bounding_boxes", "type": "List[Tuple[float, float, float, float, str]]"}
]
}

View File

@ -1,4 +1,8 @@
# Lollms function call definition file
# File Name: set_timer_with_alert.py
# Author: Saif (ParisNeo)
# Description: This function sets a non-blocking timer that shows a PyQt window with a message and makes noise after a specified duration. It works on any operating system by using the pyautogui library for the alert sound.
# Here you need to import any necessary imports depending on the function requested by the user
# example import math
@ -6,7 +10,7 @@
from functools import partial
# It is advised to import typing elements
# from typing import List
from typing import Any, Dict
# Import PackageManager if there are potential libraries that need to be installed
from lollms.utilities import PackageManager
@ -17,30 +21,35 @@ from ascii_colors import trace_exception
# Here is an example of how we install a non installed library using PackageManager
if not PackageManager.check_package_installed("PyQt5"):
PackageManager.install_package("PyQt5")
if not PackageManager.check_package_installed("pyautogui"):
PackageManager.install_package("pyautogui")
# now we can import the library
# now we can import the libraries
import threading
import time
import sys
from PyQt5.QtWidgets import QApplication, QMessageBox
import winsound
import pyautogui
# here is the core of the function to be built
def set_timer_with_alert(duration: int, message: str) -> str:
def timer_callback():
if type(duration)==str and len(duration)>0:
duration = float(duration.split()[0])
time.sleep(duration)
winsound.Beep(1000, 1000) # Make noise when time is up
"""
Sets a non-blocking timer that shows a PyQt window with a message and makes noise after a specified duration.
app = QApplication(sys.argv)
msg_box = QMessageBox()
msg_box.setIcon(QMessageBox.Information)
msg_box.setWindowTitle("Timer Alert")
msg_box.setText(message)
msg_box.setStandardButtons(QMessageBox.Ok)
msg_box.buttonClicked.connect(app.quit)
msg_box.exec_()
Parameters:
duration (int): The duration for the timer in seconds.
message (str): The message to be displayed in the alert window.
Returns:
str: A success message indicating the timer has been set.
"""
def timer_callback():
try:
time.sleep(duration)
pyautogui.alert(text=message, title="Timer Alert", button='OK')
pyautogui.beep()
except Exception as e:
return trace_exception(e)
try:
# Start the timer in a new thread to make it non-blocking
@ -53,7 +62,7 @@ def set_timer_with_alert(duration: int, message: str) -> str:
return trace_exception(e)
# Here is the metadata function that should have the name in format function_name_function
def set_timer_with_alert_function(processor, client):
def set_timer_with_alert_function() -> Dict[str, Any]:
return {
"function_name": "set_timer_with_alert", # The function name in string
"function": set_timer_with_alert, # The function to be called

View File

View File

@ -0,0 +1,45 @@
# Lollms function call definition file
# Import necessary modules
from pathlib import Path
from functools import partial
from typing import Union
from lollms.utilities import PackageManager
from lollms.personality import APScript
from lollms.tts import LollmsTTS
from safe_store import GenericDataLoader
from ascii_colors import trace_exception
# Here is the core of the function to be built
def read_text(text: str, tts_module:LollmsTTS, llm:APScript) -> str:
"""
This function takes a TTS module and a file path as input, reads the text from the file,
and uses the TTS module to generate audio from the text.
Parameters:
tts_module: The text-to-speech module with a method tts_audio.
text: The text to be read.
Returns:
str: The path to the generated audio file.
"""
try:
# Generate audio from the text
audio_file_path = tts_module.tts_audio(text)
llm.chunk(text)
llm.new_message("")
# Return the path to the generated audio file
return str(audio_file_path)
except Exception as e:
return trace_exception(e)
# Metadata function
def read_text_function(file_path:str,tts_module:LollmsTTS):
return {
"function_name": "read_text_from_file", # The function name in string
"function": partial(read_text, file_path=file_path, tts_module=tts_module), # The function to be called
"function_description": "Reads text from a file and uses a TTS module to generate audio from the text.", # Description of the function
"function_parameters": [] # The set of parameters
}

View File

@ -0,0 +1,50 @@
# Lollms function call definition file
# Import necessary modules
from pathlib import Path
from functools import partial
from typing import Union
from lollms.utilities import PackageManager
from lollms.personality import APScript
from lollms.tts import LollmsTTS
from safe_store import GenericDataLoader
from ascii_colors import trace_exception
# Here is the core of the function to be built
def read_text_from_file(file_path: Union[Path, str], tts_module:LollmsTTS, llm:APScript) -> str:
"""
This function takes a TTS module and a file path as input, reads the text from the file,
and uses the TTS module to generate audio from the text.
Parameters:
tts_module: The text-to-speech module with a method tts_audio.
file_path: The path to the text file containing the text to be read.
Returns:
str: The path to the generated audio file.
"""
try:
# Ensure file_path is of type Path
file_path = Path(file_path)
# Read the text from the file
text = GenericDataLoader.read_file(file_path)
# Generate audio from the text
audio_file_path = tts_module.tts_audio(text,use_threading=True)
llm.full(text)
# Return the path to the generated audio file
return str(audio_file_path)
except Exception as e:
return trace_exception(e)
# Metadata function
def read_text_from_file_function(file_path:str,tts_module:LollmsTTS, llm:APScript):
return {
"function_name": "read_text_from_file", # The function name in string
"function": partial(read_text_from_file, file_path=file_path, tts_module=tts_module, llm=llm), # The function to be called
"function_description": "Reads text from the current file and uses a TTS module to generate audio from the text.", # Description of the function
"function_parameters": [] # The set of parameters
}

View File

@ -0,0 +1 @@
from lollms.functions.web.google_search import google_search, google_search_function

View File

@ -0,0 +1,46 @@
# Lollms function call definition file
# Import necessary libraries
from functools import partial
from typing import List
from lollms.utilities import PackageManager
from ascii_colors import trace_exception
# Ensure the webbrowser package is available
if not PackageManager.check_package_installed("webbrowser"):
PackageManager.install_package("webbrowser")
# Import the webbrowser library
import webbrowser
# Define the function to perform a Google search
def google_search(query: str) -> str:
"""
Perform a Google search using the default web browser.
Parameters:
- query (str): The search query.
Returns:
- str: A message indicating the search was performed.
"""
try:
# Construct the Google search URL
search_url = f"https://www.google.com/search?q={query}"
# Open the search URL in the default web browser
webbrowser.open(search_url)
# Return a success message
return f"Performed Google search for query: {query}"
except Exception as e:
return trace_exception(e)
# Define the metadata function
def google_search_function():
return {
"function_name": "google_search", # The function name in string
"function": google_search, # The function to be called
"function_description": "Performs a Google search using the default web browser.", # Description of the function
"function_parameters": [{"name": "query", "type": "str"}] # The set of parameters
}

View File

@ -3394,6 +3394,7 @@ The AI should respond in this format using data from actions_list:
result = function(**parameters)
results.append(result)
except TypeError as e:
trace_exception(e)
# Handle cases where the function call fails due to incorrect parameters, etc.
results.append(f"Error calling {function_name}: {e}")
else:
@ -3521,6 +3522,20 @@ The AI should respond in this format using data from actions_list:
return function_calls
def interact(
self,
context_details,
callback = None
):
upgraded_prompt = self.build_prompt_from_context_details(context_details)
if len(self.personality.image_files)>0:
# Generate the initial text based on the upgraded prompt.
generated_text = self.fast_gen_with_images(upgraded_prompt, self.personality.image_files, callback=callback)
else:
generated_text = self.fast_gen(upgraded_prompt, callback=callback)
return generated_text
def interact_with_function_call(
self,
context_details,
@ -3528,24 +3543,26 @@ The AI should respond in this format using data from actions_list:
prompt_after_execution=True,
callback = None,
hide_function_call=False,
separate_output=False):
separate_output=False,
max_nested_function_calls=10):
start_header_id_template = self.config.start_header_id_template
end_header_id_template = self.config.end_header_id_template
system_message_template = self.config.system_message_template
separator_template = self.config.separator_template
final_output = ""
if len(self.personality.image_files)>0:
out, function_calls = self.generate_with_function_calls_and_images(context_details, self.personality.image_files, function_definitions, callback=callback)
else:
out, function_calls = self.generate_with_function_calls(context_details, function_definitions, callback=callback)
if len(function_calls)>0:
nested_function_calls = 0
while len(function_calls)>0 and nested_function_calls<max_nested_function_calls:
nested_function_calls += 1
self.chunk("\n")
if hide_function_call:
self.full("") #Hide function
if self.config.debug:
self.print_prompt("Function calls", json.dumps(function_calls, indent=4))
@ -3562,11 +3579,6 @@ The AI should respond in this format using data from actions_list:
else:
out, function_calls = self.generate_with_function_calls(context_details, function_definitions, callback=callback)
final_output += "\n" + out
if len(function_calls)>0:
outputs = self.execute_function_calls(function_calls,function_definitions)
final_output = "\n".join([str(o) if type(o)==str else str(o[0]) if (type(o)==tuple or type(0)==list) and len(o)>0 else "" for o in outputs])
out += f"{separator_template}{start_header_id_template}function calls results{end_header_id_template}\n" + final_output
context_details["discussion_messages"] +=out
else:
final_output = out
return final_output