diff --git a/lollms/functions/__init__.py b/lollms/functions/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lollms/functions/generate_image.py b/lollms/functions/generate_image.py
new file mode 100644
index 0000000..1256d02
--- /dev/null
+++ b/lollms/functions/generate_image.py
@@ -0,0 +1,50 @@
+from lollms.utilities import PackageManager, find_first_available_file_index, discussion_path_to_url
+from lollms.client_session import Client
+from lollms.personality import APScript
+if not PackageManager.check_package_installed("pyautogui"):
+ PackageManager.install_package("pyautogui")
+if not PackageManager.check_package_installed("PyQt5"):
+ PackageManager.install_package("PyQt5")
+from ascii_colors import trace_exception
+import cv2
+import time
+from PyQt5 import QtWidgets, QtGui, QtCore
+import sys
+
+def build_image(prompt, width, height, self:APScript, client:Client):
+ try:
+ if self.personality_config.image_generation_engine=="autosd":
+ if not hasattr(self, "sd"):
+ from lollms.services.sd.lollms_sd import LollmsSD
+ self.step_start("Loading ParisNeo's fork of AUTOMATIC1111's stable diffusion service")
+ self.sd = LollmsSD(self.personality.app, self.personality.name, max_retries=-1,auto_sd_base_url=self.personality.config.sd_base_url)
+ self.step_end("Loading ParisNeo's fork of AUTOMATIC1111's stable diffusion service")
+ file, infos = self.sd.paint(
+ prompt,
+ "",
+ self.personality.image_files,
+ width = width,
+ height = height,
+ output_path=client.discussion.discussion_folder
+ )
+ elif self.personality_config.image_generation_engine in ["dall-e-2", "dall-e-3"]:
+ if not hasattr(self, "dalle"):
+ from lollms.services.dalle.lollms_dalle import LollmsDalle
+ self.step_start("Loading dalle service")
+ self.dalle = LollmsDalle(self.personality.app, self.personality.config.dall_e_key, self.personality_config.image_generation_engine)
+ self.step_end("Loading dalle service")
+ self.step_start("Painting")
+ file = self.dalle.paint(
+ prompt,
+ width = width,
+ height = height,
+ output_path=client.discussion.discussion_folder
+ )
+ self.step_end("Painting")
+
+ file = str(file)
+ escaped_url = discussion_path_to_url(file)
+ return f'\n![]({escaped_url})'
+ except Exception as ex:
+ trace_exception(ex)
+ return "Couldn't generate image. Make sure Auto1111's stable diffusion service is installed"
\ No newline at end of file
diff --git a/lollms/functions/take_a_photo.py b/lollms/functions/take_a_photo.py
new file mode 100644
index 0000000..d5ab4ea
--- /dev/null
+++ b/lollms/functions/take_a_photo.py
@@ -0,0 +1,115 @@
+from lollms.utilities import PackageManager, find_first_available_file_index, discussion_path_to_url
+from lollms.client_session import Client
+if not PackageManager.check_package_installed("pyautogui"):
+ PackageManager.install_package("pyautogui")
+if not PackageManager.check_package_installed("PyQt5"):
+ PackageManager.install_package("PyQt5")
+
+import cv2
+import time
+from PyQt5 import QtWidgets, QtGui, QtCore
+import sys
+
+class CameraWindow(QtWidgets.QWidget):
+ def __init__(self):
+ super().__init__()
+ self.initUI()
+ self.cap = cv2.VideoCapture(0)
+ self.timer = QtCore.QTimer()
+ self.timer.timeout.connect(self.update_frame)
+ self.timer.start(50)
+
+ def initUI(self):
+ self.setWindowTitle('Camera')
+
+ self.image_label = QtWidgets.QLabel(self)
+ self.image_label.resize(640, 480)
+
+ self.captured_image_label = QtWidgets.QLabel(self)
+ self.captured_image_label.resize(640, 480)
+
+ self.take_shot_button = QtWidgets.QPushButton('Take Shot', self)
+ self.take_shot_button.clicked.connect(self.take_shot)
+
+ self.ok_button = QtWidgets.QPushButton('OK', self)
+ self.ok_button.clicked.connect(self.ok)
+
+ self.hbox_layout = QtWidgets.QHBoxLayout()
+ self.hbox_layout.addWidget(self.image_label)
+ self.hbox_layout.addWidget(self.captured_image_label)
+
+ self.vbox_layout = QtWidgets.QVBoxLayout()
+ self.vbox_layout.addLayout(self.hbox_layout)
+ self.vbox_layout.addWidget(self.take_shot_button)
+ self.vbox_layout.addWidget(self.ok_button)
+ self.setLayout(self.vbox_layout)
+
+ def update_frame(self):
+ ret, frame = self.cap.read()
+ if ret:
+ self.frame = frame
+ image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
+ height, width, channel = image.shape
+ step = channel * width
+ qImg = QtGui.QImage(image.data, width, height, step, QtGui.QImage.Format_RGB888)
+ self.image_label.setPixmap(QtGui.QPixmap.fromImage(qImg))
+
+ def take_shot(self):
+ if hasattr(self, 'frame'):
+ self.captured_frame = self.frame
+ image = cv2.cvtColor(self.captured_frame, cv2.COLOR_BGR2RGB)
+ height, width, channel = image.shape
+ step = channel * width
+ qImg = QtGui.QImage(image.data, width, height, step, QtGui.QImage.Format_RGB888)
+ self.captured_image_label.setPixmap(QtGui.QPixmap.fromImage(qImg))
+
+ def ok(self):
+ if hasattr(self, 'captured_frame'):
+ self.close()
+
+ def closeEvent(self, event):
+ self.cap.release()
+ event.accept()
+
+def take_photo(client, use_ui=False):
+ if use_ui:
+ def run_app():
+ app = QtWidgets.QApplication(sys.argv)
+ win = CameraWindow()
+ win.show()
+ app.exec_()
+ return win
+
+ win = run_app()
+
+ if hasattr(win, 'captured_frame'):
+ frame = win.captured_frame
+ else:
+ return "Failed to capture image."
+ else:
+ # Attempt to access the webcam
+ cap = cv2.VideoCapture(0)
+
+ if not cap.isOpened():
+ return "\nWebcam is not connected."
+
+ # Capture a single frame
+ n = time.time()
+ ret, frame = cap.read()
+ while(time.time()-n<2):
+ ret, frame = cap.read()
+
+ if not ret:
+ return "Failed to capture image."
+
+ cap.release()
+
+ view_image = client.discussion.discussion_folder/"view_images"
+ image = client.discussion.discussion_folder/"images"
+ index = find_first_available_file_index(view_image,"screen_shot_",".png")
+ fn_view = view_image/f"screen_shot_{index}.png"
+ cv2.imwrite(str(fn_view), frame)
+ fn = image/f"screen_shot_{index}.png"
+ cv2.imwrite(str(fn), frame)
+ client.discussion.image_files.append(fn)
+ return f''
diff --git a/lollms/functions/take_screen_shot.py b/lollms/functions/take_screen_shot.py
new file mode 100644
index 0000000..5746888
--- /dev/null
+++ b/lollms/functions/take_screen_shot.py
@@ -0,0 +1,62 @@
+from lollms.utilities import PackageManager, find_first_available_file_index, discussion_path_to_url
+from lollms.client_session import Client
+if not PackageManager.check_package_installed("pyautogui"):
+ PackageManager.install_package("pyautogui")
+if not PackageManager.check_package_installed("PyQt5"):
+ PackageManager.install_package("PyQt5")
+
+import pyautogui
+from PyQt5 import QtWidgets, QtGui
+from PyQt5.QtCore import Qt
+import sys
+class ScreenshotWindow(QtWidgets.QWidget):
+ def __init__(self, client, screenshot, fn_view, fn):
+ super().__init__()
+ self.client = client
+ self.screenshot = screenshot
+ self.fn_view = fn_view
+ self.fn = fn
+
+ self.initUI()
+
+ def initUI(self):
+ self.setWindowTitle('Screenshot Viewer')
+ self.layout = QtWidgets.QVBoxLayout()
+
+ self.label = QtWidgets.QLabel(self)
+ self.pixmap = QtGui.QPixmap(self.screenshot)
+ self.label.setPixmap(self.pixmap)
+ self.layout.addWidget(self.label)
+
+ self.ok_button = QtWidgets.QPushButton('OK')
+ self.ok_button.clicked.connect(self.save_and_close)
+ self.layout.addWidget(self.ok_button)
+
+ self.setLayout(self.layout)
+
+ def save_and_close(self):
+ self.screenshot.save(self.fn_view)
+ self.screenshot.save(self.fn)
+ self.client.discussion.image_files.append(self.fn)
+ self.close()
+
+
+def take_screenshot(self, client: Client, use_ui: bool = False):
+ screenshot = pyautogui.screenshot()
+ view_image = client.discussion.discussion_folder / "view_images"
+ image = client.discussion.discussion_folder / "images"
+ index = find_first_available_file_index(view_image, "screen_shot_", ".png")
+ fn_view = view_image / f"screen_shot_{index}.png"
+ fn = image / f"screen_shot_{index}.png"
+
+ if use_ui:
+ app = QtWidgets.QApplication(sys.argv)
+ window = ScreenshotWindow(client, screenshot, fn_view, fn)
+ window.show()
+ app.exec_()
+ return f''
+ else:
+ screenshot.save(fn_view)
+ screenshot.save(fn)
+ client.discussion.image_files.append(fn)
+ return f''
\ No newline at end of file
diff --git a/lollms/utilities.py b/lollms/utilities.py
index 18e4e1b..cf10464 100644
--- a/lollms/utilities.py
+++ b/lollms/utilities.py
@@ -384,6 +384,17 @@ def discussion_path_to_url(file_path:str|Path)->str:
url = "/"+file_path[file_path.index("discussion_databases"):].replace("\\","/").replace("discussion_databases","discussions")
return "/".join([urllib.parse.quote(p, safe="") for p in url.split("/")])
+def personality_path_to_url(file_path:str|Path)->str:
+ """
+ This function takes a file path as an argument and converts it into a URL format. It first removes the initial part of the file path until the "outputs" string is reached, then replaces backslashes with forward slashes and quotes each segment with urllib.parse.quote() before joining them with forward slashes to form the final URL.
+
+ :param file_path: str, the file path in the format of a Windows system
+ :return: str, the converted URL format of the given file path
+ """
+ file_path = str(file_path)
+ url = "/"+file_path[file_path.index("personalities_zoo"):].replace("\\","/").replace("personalities_zoo","personalities")
+ return "/".join([urllib.parse.quote(p, safe="") for p in url.split("/")])
+
def url2host_port(url, default_port =8000):
if "http" in url: