diff --git a/cognee-gui.py b/cognee-gui.py new file mode 100644 index 000000000..f5cf55210 --- /dev/null +++ b/cognee-gui.py @@ -0,0 +1,133 @@ +import sys +import asyncio +import cognee + +try: + from PySide6.QtWidgets import ( + QApplication, + QWidget, + QPushButton, + QLineEdit, + QFileDialog, + QVBoxLayout, + QLabel, + QMessageBox, + QTextEdit, + QProgressDialog, + ) + from PySide6.QtCore import Qt + + from qasync import QEventLoop # Import QEventLoop from qasync +except ImportError as e: + print( + "\nPlease install Cognee with optional gui dependencies or manually install missing dependencies.\n" + ) + print("\nTo install with poetry use:") + print("\npoetry install -E gui\n") + print("\nOr to install with poetry and all dependencies use:") + print("\npoetry install --all-extras\n") + print("\nTo install with pip use: ") + print('\npip install ".[gui]"\n') + raise e + + +class FileSearchApp(QWidget): + def __init__(self): + super().__init__() + self.selected_file = None + self.init_ui() + + def init_ui(self): + # Button to open file dialog + self.file_button = QPushButton("Upload File to Cognee", parent=self) + self.file_button.clicked.connect(self.open_file_dialog) + + # Label to display selected file path + self.file_label = QLabel("No file selected", parent=self) + + # Line edit for search input + self.search_input = QLineEdit(parent=self) + self.search_input.setPlaceholderText("Enter text to search...") + + # Button to perform search; schedule the async search on click + self.search_button = QPushButton("Cognee Search", parent=self) + self.search_button.clicked.connect(lambda: asyncio.ensure_future(self._cognee_search())) + + # Text output area for search results + self.result_output = QTextEdit(parent=self) + self.result_output.setReadOnly(True) + self.result_output.setPlaceholderText("Search results will appear here...") + + # Progress dialog + self.progress_dialog = QProgressDialog("Processing..", None, 0, 0, parent=self) + self.progress_dialog.setWindowModality(Qt.WindowModal) + # self.progress_dialog.setAttribute(Qt.WA_DeleteOnClose) + self.progress_dialog.setCancelButton(None) # Remove the cancel button + self.progress_dialog.close() + + # Layout setup + layout = QVBoxLayout() + layout.addWidget(self.file_button) + layout.addWidget(self.file_label) + layout.addWidget(self.search_input) + layout.addWidget(self.search_button) + layout.addWidget(self.result_output) + + self.setLayout(layout) + self.setWindowTitle("Cognee") + self.resize(500, 300) + + def open_file_dialog(self): + file_path, _ = QFileDialog.getOpenFileName( + self, "Select a File", "", "All Files (*.*);;Text Files (*.txt)" + ) + if file_path: + self.selected_file = file_path + self.file_label.setText(f"Selected: {file_path}") + asyncio.ensure_future(self.process_file_async()) + + async def process_file_async(self): + """Asynchronously add and process the selected file.""" + # Disable the entire window + self.progress_dialog.show() + self.setEnabled(False) + try: + await cognee.add(self.selected_file) + await cognee.cognify() + except Exception as e: + QMessageBox.critical(self, "Error", f"File processing failed: {str(e)}") + # Once finished, re-enable the window + self.setEnabled(True) + self.progress_dialog.close() + + async def _cognee_search(self): + """Performs an async search and updates the result output.""" + # Disable the entire window + self.setEnabled(False) + self.progress_dialog.show() + + try: + search_text = self.search_input.text().strip() + result = await cognee.search(query_text=search_text) + print(result) + # Assuming result is a list-like object; adjust if necessary + self.result_output.setText(result[0]) + except Exception as e: + QMessageBox.critical(self, "Error", f"Search failed: {str(e)}") + + # Once finished, re-enable the window + self.setEnabled(True) + self.progress_dialog.close() + + +if __name__ == "__main__": + app = QApplication(sys.argv) + # Create a qasync event loop and set it as the current event loop + loop = QEventLoop(app) + asyncio.set_event_loop(loop) + + window = FileSearchApp() + window.show() + + with loop: + loop.run_forever() diff --git a/cognee/api/v1/search/routers/get_search_router.py b/cognee/api/v1/search/routers/get_search_router.py index c5f240eed..cb3ef38a8 100644 --- a/cognee/api/v1/search/routers/get_search_router.py +++ b/cognee/api/v1/search/routers/get_search_router.py @@ -10,7 +10,7 @@ from cognee.modules.users.methods import get_authenticated_user class SearchPayloadDTO(InDTO): - search_type: SearchType + search_type: SearchType query: str @@ -38,8 +38,9 @@ def get_search_router() -> APIRouter: from cognee.api.v1.search import search as cognee_search try: - - results = await cognee_search(query_text = payload.query, query_type = payload.search_type, user=user) + results = await cognee_search( + query_text=payload.query, query_type=payload.search_type, user=user + ) return results except Exception as error: diff --git a/cognee/tasks/completion/graph_query_completion.py b/cognee/tasks/completion/graph_query_completion.py index 6503a04e4..c2780601b 100644 --- a/cognee/tasks/completion/graph_query_completion.py +++ b/cognee/tasks/completion/graph_query_completion.py @@ -58,7 +58,7 @@ async def graph_query_completion(query: str) -> list: "context": retrieved_edges_to_string(found_triplets), } user_prompt = render_prompt("graph_context_for_question.txt", args) - system_prompt = read_query_prompt("answer_simple_question_restricted.txt") + system_prompt = read_query_prompt("answer_simple_question.txt") llm_client = get_llm_client() computed_answer = await llm_client.acreate_structured_output( diff --git a/poetry.lock b/poetry.lock index 5a2c9340a..39aadbcb5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "aiofiles" @@ -5510,8 +5510,8 @@ files = [ [package.dependencies] numpy = [ {version = ">=1.22.4", markers = "python_version < \"3.11\""}, - {version = ">=1.23.2", markers = "python_version == \"3.11\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, + {version = ">=1.23.2", markers = "python_version == \"3.11\""}, ] python-dateutil = ">=2.8.2" pytz = ">=2020.1" @@ -6572,8 +6572,8 @@ astroid = ">=3.3.8,<=3.4.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, - {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, ] isort = ">=4.2.5,<5.13.0 || >5.13.0,<7" mccabe = ">=0.6,<0.8" @@ -6688,6 +6688,57 @@ files = [ [package.extras] dev = ["build", "flake8", "mypy", "pytest", "twine"] +[[package]] +name = "pyside6" +version = "6.8.2.1" +description = "Python bindings for the Qt cross-platform application and UI framework" +optional = true +python-versions = "<3.14,>=3.9" +files = [ + {file = "PySide6-6.8.2.1-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:3fcb551729f235475b2abe7d919027de54a65d850e744f60716f890202273720"}, + {file = "PySide6-6.8.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:23d2a1a77b25459a049c4276b4e0bbfb375b73d3921061b1a16bcfa64e1fe517"}, + {file = "PySide6-6.8.2.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:bfefa80a93db06dc64c0e7beef0377c9b8ca51e007cfc34575defe065af893b6"}, + {file = "PySide6-6.8.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:92361e41727910e3560ea5ba494fabecc76cd20892c9fcb2ced07619081c4e65"}, +] + +[package.dependencies] +PySide6-Addons = "6.8.2.1" +PySide6-Essentials = "6.8.2.1" +shiboken6 = "6.8.2.1" + +[[package]] +name = "pyside6-addons" +version = "6.8.2.1" +description = "Python bindings for the Qt cross-platform application and UI framework (Addons)" +optional = true +python-versions = "<3.14,>=3.9" +files = [ + {file = "PySide6_Addons-6.8.2.1-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:5558816018042fecd0d782111ced529585a23ea9a010b518f8495764f578a01f"}, + {file = "PySide6_Addons-6.8.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f3d85e676851ada8238bc76ebfacbee738fc0b35b3bc15c9765dd107b8ee6ec4"}, + {file = "PySide6_Addons-6.8.2.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:d904179f16deeca4ba440b4ef78e8d54df2b994b46784ad9d53b741082f3b2a7"}, + {file = "PySide6_Addons-6.8.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:c761cc45022aa79d8419e671e7fb34a4a3e5b3826f1e68fcb819bd6e3a387fbb"}, +] + +[package.dependencies] +PySide6-Essentials = "6.8.2.1" +shiboken6 = "6.8.2.1" + +[[package]] +name = "pyside6-essentials" +version = "6.8.2.1" +description = "Python bindings for the Qt cross-platform application and UI framework (Essentials)" +optional = true +python-versions = "<3.14,>=3.9" +files = [ + {file = "PySide6_Essentials-6.8.2.1-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:ae5cc48f7e9a08e73e3ec2387ce245c8150e620b8d5a87548ebd4b8e3aeae49b"}, + {file = "PySide6_Essentials-6.8.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5ab31e5395a4724102edd6e8ff980fa3f7cde2aa79050763a1dcc30bb914195a"}, + {file = "PySide6_Essentials-6.8.2.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:7aed46f91d44399b4c713cf7387f5fb6f0114413fbcdbde493a528fb8e19f6ed"}, + {file = "PySide6_Essentials-6.8.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:18de224f09108998d194e60f2fb8a1e86367dd525dd8a6192598e80e6ada649e"}, +] + +[package.dependencies] +shiboken6 = "6.8.2.1" + [[package]] name = "pysocks" version = "1.7.1" @@ -7151,6 +7202,17 @@ files = [ [package.dependencies] cffi = {version = "*", markers = "implementation_name == \"pypy\""} +[[package]] +name = "qasync" +version = "0.27.1" +description = "Python library for using asyncio in Qt-based applications" +optional = true +python-versions = ">=3.8,<4.0" +files = [ + {file = "qasync-0.27.1-py3-none-any.whl", hash = "sha256:5d57335723bc7d9b328dadd8cb2ed7978640e4bf2da184889ce50ee3ad2602c7"}, + {file = "qasync-0.27.1.tar.gz", hash = "sha256:8dc768fd1ee5de1044c7c305eccf2d39d24d87803ea71189d4024fb475f4985f"}, +] + [[package]] name = "qdrant-client" version = "1.13.2" @@ -8036,6 +8098,19 @@ files = [ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, ] +[[package]] +name = "shiboken6" +version = "6.8.2.1" +description = "Python/C++ bindings helper module" +optional = true +python-versions = "<3.14,>=3.9" +files = [ + {file = "shiboken6-6.8.2.1-cp39-abi3-macosx_12_0_universal2.whl", hash = "sha256:d3dedeb3732ecfc920c9f97da769c0022a1c3bda99346a9eba56fbf093deaa75"}, + {file = "shiboken6-6.8.2.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c83e90056f13d0872cc4d2b7bf60b6d6e3b1b172f1f91910c0ba5b641af01758"}, + {file = "shiboken6-6.8.2.1-cp39-abi3-manylinux_2_39_aarch64.whl", hash = "sha256:8592401423acc693f51dbbfae5e7493cc3ed6738be79daaf90afa07f4da5bb25"}, + {file = "shiboken6-6.8.2.1-cp39-abi3-win_amd64.whl", hash = "sha256:1b751d47b759762b7ca31bad278d52eca4105d3028880d93979261ebbfba810c"}, +] + [[package]] name = "simplejson" version = "3.19.3" @@ -9670,6 +9745,7 @@ falkordb = ["falkordb"] filesystem = ["botocore"] gemini = ["google-generativeai"] groq = ["groq"] +gui = ["pyside6", "qasync"] huggingface = ["transformers"] langchain = ["langchain_text_splitters", "langsmith"] llama-index = ["llama-index-core"] @@ -9685,4 +9761,4 @@ weaviate = ["weaviate-client"] [metadata] lock-version = "2.0" python-versions = ">=3.10.0,<3.13" -content-hash = "2029859075342dacf6c2f2e993894daef07e50a5e2047152158bf9116a48579b" +content-hash = "d384b6028d84b344b40b6c7e047d592700227409aa3a4d961e157cd824fa50b5" diff --git a/pyproject.toml b/pyproject.toml index 97a774c43..a56c5db45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,6 +84,8 @@ tree-sitter = {version = "^0.24.0", optional = true} tree-sitter-python = {version = "^0.23.6", optional = true} plotly = {version = "^6.0.0", optional = true} gdown = {version = "^5.2.0", optional = true} +pyside6 = {version = "^6.8.2.1", optional = true} +qasync = {version = "^0.27.1", optional = true} [tool.poetry.extras] @@ -106,6 +108,7 @@ milvus = ["pymilvus"] docs = ["unstructured"] codegraph = ["fastembed", "tree-sitter", "tree-sitter-python"] evals = ["plotly", "gdown"] +gui = ["pyside6", "qasync"] [tool.poetry.group.dev.dependencies] pytest = "^7.4.0"