mirror of
https://github.com/ParisNeo/lollms.git
synced 2025-01-21 03:55:01 +00:00
enhanced functions
This commit is contained in:
parent
a52db1fb9f
commit
7da874228b
7
lollms/functions/analyze_code/__init__.py
Normal file
7
lollms/functions/analyze_code/__init__.py
Normal 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
|
||||
|
58
lollms/functions/analyze_code/add_function_to_file.py
Normal file
58
lollms/functions/analyze_code/add_function_to_file.py
Normal 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"},
|
||||
]
|
||||
}
|
@ -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
|
||||
@ -130,101 +134,3 @@ def create_project_database_function(project_path, 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 "}
|
||||
]
|
||||
}
|
@ -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 "}
|
||||
]
|
||||
}
|
@ -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."}
|
||||
]
|
||||
}
|
85
lollms/functions/analyze_code/update_class_in_file.py
Normal file
85
lollms/functions/analyze_code/update_class_in_file.py
Normal 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"},
|
||||
]
|
||||
}
|
70
lollms/functions/analyze_code/update_function_in_file.py
Normal file
70
lollms/functions/analyze_code/update_function_in_file.py
Normal 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"},
|
||||
]
|
||||
}
|
75
lollms/functions/image_management/draw_bounding_boxes.py
Normal file
75
lollms/functions/image_management/draw_bounding_boxes.py
Normal 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]]"}
|
||||
]
|
||||
}
|
@ -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
|
||||
|
0
lollms/functions/tts/__init__.py
Normal file
0
lollms/functions/tts/__init__.py
Normal file
45
lollms/functions/tts/read_text.py
Normal file
45
lollms/functions/tts/read_text.py
Normal 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
|
||||
}
|
50
lollms/functions/tts/read_text_from_file.py
Normal file
50
lollms/functions/tts/read_text_from_file.py
Normal 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
|
||||
}
|
1
lollms/functions/web/__init__.py
Normal file
1
lollms/functions/web/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from lollms.functions.web.google_search import google_search, google_search_function
|
46
lollms/functions/web/google_search.py
Normal file
46
lollms/functions/web/google_search.py
Normal 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
|
||||
}
|
@ -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,21 +3543,23 @@ 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
|
||||
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user