diff --git a/docs/get-started/full-stack.mdx b/docs/get-started/full-stack.mdx new file mode 100644 index 00000000..f9ed9cd2 --- /dev/null +++ b/docs/get-started/full-stack.mdx @@ -0,0 +1,35 @@ +--- +title: 'šŸ’» Full stack' +--- + +Embedchain provides a clean and simple cli utility that lets you create full-stack RAG applications locally with a single comand. + +## Prerequisite + +Make sure that you have installed the following: +- Embedchain python package (`pip install embedchain`) +- [Node.js](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) and [Yarn](https://classic.yarnpkg.com/lang/en/docs/install/) + +## Get started + +For the purpose of the demo, you have to set `OPENAI_API_KEY` to start with but you can choose any llm by changing the configuration easily. + +Now run the following command: + +```bash +ec runserver +``` + +Once you run this command, Embedchain does the following: + +1. Fetch full stack template that uses FastAPI for backend, and Next.JS template for frontend +2. Install necessary requirements +3. Launch the frontend and backend server for you to interact with. + +Once you are done, visit `http://localhost:3000` and you will see a chat UI as shown below. + +![full stack example](/images/fullstack.png) + +You can navigate to [Embedchain admin panel] where you can see the chunks created for your documents that you ingested for your RAG application. Below is a screenshot for the same: + +![full stack chunks](/images/fullstack-chunks.png) diff --git a/docs/images/fullstack-chunks.png b/docs/images/fullstack-chunks.png new file mode 100644 index 00000000..ba4505ba Binary files /dev/null and b/docs/images/fullstack-chunks.png differ diff --git a/docs/images/fullstack.png b/docs/images/fullstack.png new file mode 100644 index 00000000..ba73bc06 Binary files /dev/null and b/docs/images/fullstack.png differ diff --git a/docs/mint.json b/docs/mint.json index b4f8a641..33ca4d41 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -63,6 +63,7 @@ "get-started/quickstart", "get-started/introduction", "get-started/faq", + "get-started/full-stack", { "group": "šŸ”— Integrations", "pages": [ diff --git a/embedchain/cli.py b/embedchain/cli.py index 17c3d6be..4037b65f 100644 --- a/embedchain/cli.py +++ b/embedchain/cli.py @@ -2,10 +2,16 @@ import json import os import re import shutil +import signal import subprocess +import sys +import tempfile +import zipfile +from pathlib import Path import click import pkg_resources +import requests from rich.console import Console from embedchain.telemetry.posthog import AnonymousTelemetry @@ -21,6 +27,23 @@ def cli(): anonymous_telemetry = AnonymousTelemetry() +api_process = None +ui_process = None + + +def signal_handler(sig, frame): + """Signal handler to catch termination signals and kill server processes.""" + global api_process, ui_process + console.print("\nšŸ›‘ [bold yellow]Stopping servers...[/bold yellow]") + if api_process: + api_process.terminate() + console.print("šŸ›‘ [bold yellow]API server stopped.[/bold yellow]") + if ui_process: + ui_process.terminate() + console.print("šŸ›‘ [bold yellow]UI server stopped.[/bold yellow]") + sys.exit(0) + + def get_pkg_path_from_name(template: str): try: # Determine the installation location of the embedchain package @@ -414,3 +437,99 @@ def deploy(): deploy_hf_spaces(ec_app_name) else: console.print("āŒ [bold red]No recognized deployment platform found.[/bold red]") + + +@cli.command() +def runserver(): + # Set up signal handling + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + # Check if 'api' and 'ui' directories exist + if os.path.exists("api") and os.path.exists("ui"): + pass + else: + # Step 1: Download the zip file + zip_url = "http://github.com/embedchain/ec-admin/archive/main.zip" + try: + response = requests.get(zip_url) + response.raise_for_status() + with tempfile.NamedTemporaryFile(delete=False) as tmp_file: + tmp_file.write(response.content) + zip_file_path = tmp_file.name + console.print("āœ… [bold green]Downloaded zip file successfully.[/bold green]") + except requests.RequestException as e: + console.print(f"āŒ [bold red]Failed to download zip file: {e}[/bold red]") + return + + # Step 2: Extract the zip file + try: + with zipfile.ZipFile(zip_file_path, "r") as zip_ref: + # Get the name of the root directory inside the zip file + root_dir = Path(zip_ref.namelist()[0]) + for member in zip_ref.infolist(): + # Build the path to extract the file to, skipping the root directory + target_file = Path(member.filename).relative_to(root_dir) + source_file = zip_ref.open(member, "r") + if member.is_dir(): + # Create directory if it doesn't exist + os.makedirs(target_file, exist_ok=True) + else: + with open(target_file, "wb") as file: + # Write the file + shutil.copyfileobj(source_file, file) + console.print("āœ… [bold green]Extracted zip file successfully.[/bold green]") + except zipfile.BadZipFile: + console.print("āŒ [bold red]Error in extracting zip file. The file might be corrupted.[/bold red]") + return + + # Step 3: Install API requirements + try: + os.chdir("api") + subprocess.run(["pip", "install", "-r", "requirements.txt"], check=True) + os.chdir("..") + console.print("āœ… [bold green]Installed API requirements successfully.[/bold green]") + except Exception as e: + console.print(f"āŒ [bold red]Failed to install API requirements: {e}[/bold red]") + return + + # Step 4: Start the API server + try: + os.chdir("api") + api_process = subprocess.Popen( + ["uvicorn", "main:app", "--reload", "--host", "127.0.0.1", "--port", "8000"], stdout=None, stderr=None + ) + os.chdir("..") + console.print("āœ… [bold green]API server started successfully.[/bold green]") + except Exception as e: + console.print(f"āŒ [bold red]Failed to start the API server: {e}[/bold red]") + return + + # Step 5: Install UI requirements and start the UI server + try: + os.chdir("ui") + subprocess.run(["yarn"], check=True) + ui_process = subprocess.Popen(["yarn", "dev"], stdout=None, stderr=None) + console.print("āœ… [bold green]UI server started successfully.[/bold green]") + except Exception as e: + console.print(f"āŒ [bold red]Failed to start the UI server: {e}[/bold red]") + + # Wait for the subprocesses to complete + api_process.wait() + ui_process.wait() + + # Step 6: Install UI requirements and start the UI server + try: + os.chdir("ui") + subprocess.run(["yarn"], check=True) + subprocess.Popen(["yarn", "dev"]) + console.print("āœ… [bold green]UI server started successfully.[/bold green]") + except Exception as e: + console.print(f"āŒ [bold red]Failed to start the UI server: {e}[/bold red]") + + # Keep the script running until it receives a kill signal + try: + api_process.wait() + ui_process.wait() + except KeyboardInterrupt: + console.print("\nšŸ›‘ [bold yellow]Stopping server...[/bold yellow]") diff --git a/pyproject.toml b/pyproject.toml index 3e0f09f0..b4b1fdd0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "embedchain" -version = "0.1.51" +version = "0.1.52" description = "Data platform for LLMs - Load, index, retrieve and sync any unstructured data" authors = [ "Taranjeet Singh ",