diff --git a/cookbook/README.md b/cookbook/README.md deleted file mode 100644 index fe1cb2c6..00000000 --- a/cookbook/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## 📚 Official Cookbook - -Looking for examples and guides? Then head over to the official ScrapeGraph SDK [Cookbook](https://github.com/ScrapeGraphAI/scrapegraph-sdk/tree/main/cookbook)! - -The cookbook provides step-by-step instructions, practical examples, and tips to help you get started and make the most out of ScrapeGraph SDK. - -You will find some colab notebooks with our partners as well, such as Langchain 🦜 and LlamaIndex 🦙 - -Happy scraping! 🚀 diff --git a/docs/source/getting_started/installation.rst b/docs/source/getting_started/installation.rst index 666322af..30acfb5a 100644 --- a/docs/source/getting_started/installation.rst +++ b/docs/source/getting_started/installation.rst @@ -25,18 +25,18 @@ The library is available on PyPI, so it can be installed using the following com It is higly recommended to install the library in a virtual environment (conda, venv, etc.) -If your clone the repository, it is recommended to use a package manager like `rye `_. -To install the library using rye, you can run the following command: +If your clone the repository, it is recommended to use a package manager like `uv `_. +To install the library using uv, you can run the following command: .. code-block:: bash - rye pin 3.10 - rye sync - rye build + uv pin 3.10 + uv sync + uv build .. caution:: - **Rye** must be installed first by following the instructions on the `official website `_. + **Rye** must be installed first by following the instructions on the `official website `_. Additionally on Windows when using WSL ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/source/introduction/overview.rst b/docs/source/introduction/overview.rst index 4e2bd604..4dcaadbe 100644 --- a/docs/source/introduction/overview.rst +++ b/docs/source/introduction/overview.rst @@ -30,37 +30,93 @@ ScrapGraphAI supports a wide range of AI models from various providers. Each mod OpenAI Models ------------- - GPT-3.5 Turbo (16,385 tokens) -- GPT-4 (8,192 tokens) +- GPT-3.5 (4,096 tokens) +- GPT-3.5 Turbo Instruct (4,096 tokens) - GPT-4 Turbo Preview (128,000 tokens) -- GPT-4o (128000 tokens) -- GTP-4o-mini (128000 tokens) +- GPT-4 Vision Preview (128,000 tokens) +- GPT-4 (8,192 tokens) +- GPT-4 32k (32,768 tokens) +- GPT-4o (128,000 tokens) +- O1 Preview (128,000 tokens) +- O1 Mini (128,000 tokens) Azure OpenAI Models ------------------- - GPT-3.5 Turbo (16,385 tokens) -- GPT-4 (8,192 tokens) +- GPT-3.5 (4,096 tokens) - GPT-4 Turbo Preview (128,000 tokens) -- GPT-4o (128000 tokens) -- GTP-4o-mini (128000 tokens) +- GPT-4 (8,192 tokens) +- GPT-4 32k (32,768 tokens) +- GPT-4o (128,000 tokens) +- O1 Preview (128,000 tokens) +- O1 Mini (128,000 tokens) Google AI Models ---------------- - Gemini Pro (128,000 tokens) +- Gemini 1.5 Flash (128,000 tokens) - Gemini 1.5 Pro (128,000 tokens) +- Gemini 1.0 Pro (128,000 tokens) Anthropic Models ---------------- - Claude Instant (100,000 tokens) -- Claude 2 (200,000 tokens) +- Claude 2 (9,000 tokens) +- Claude 2.1 (200,000 tokens) - Claude 3 (200,000 tokens) +- Claude 3.5 (200,000 tokens) +- Claude 3 Opus (200,000 tokens) +- Claude 3 Sonnet (200,000 tokens) +- Claude 3 Haiku (200,000 tokens) Mistral AI Models ----------------- -- Mistral Large (128,000 tokens) +- Mistral Large Latest (128,000 tokens) +- Open Mistral Nemo (128,000 tokens) +- Codestral Latest (32,000 tokens) - Open Mistral 7B (32,000 tokens) - Open Mixtral 8x7B (32,000 tokens) +- Open Mixtral 8x22B (64,000 tokens) +- Open Codestral Mamba (256,000 tokens) -For a complete list of supported models and their token limits, please refer to the API documentation. +Ollama Models +------------- +- Command-R (12,800 tokens) +- CodeLlama (16,000 tokens) +- DBRX (32,768 tokens) +- DeepSeek Coder 33B (16,000 tokens) +- Llama2 Series (4,096 tokens) +- Llama3 Series (8,192-128,000 tokens) +- Mistral Models (32,000-128,000 tokens) +- Mixtral 8x22B Instruct (65,536 tokens) +- Phi3 Series (12,800-128,000 tokens) +- Qwen Series (32,000 tokens) + +Hugging Face Models +------------------ +- Grok-1 (8,192 tokens) +- Meta Llama 3 Series (8,192 tokens) +- Google Gemma Series (8,192 tokens) +- Microsoft Phi Series (2,048-131,072 tokens) +- GPT-2 Series (1,024 tokens) +- DeepSeek V2 Series (131,072 tokens) + +Bedrock Models +------------- +- Claude 3 Series (200,000 tokens) +- Llama2 & Llama3 Series (4,096-8,192 tokens) +- Mistral Series (32,768 tokens) +- Titan Embed Text (8,000 tokens) +- Cohere Embed (512 tokens) + +Fireworks Models +--------------- +- Llama V2 7B (4,096 tokens) +- Mixtral 8x7B Instruct (4,096 tokens) +- Llama 3.1 Series (131,072 tokens) +- Mixtral MoE Series (65,536 tokens) + +For a complete and up-to-date list of supported models and their token limits, please refer to the API documentation. Understanding token limits is crucial for optimizing your scraping tasks. Larger token limits allow for processing more text in a single API call, which can be beneficial for scraping lengthy web pages or documents. @@ -139,3 +195,8 @@ Sponsors :width: 15% :alt: Stat Proxies :target: https://dashboard.statproxies.com/?refferal=scrapegraph + +.. image:: ../../assets/scrapedo.png + :width: 11% + :alt: Scrapedo + :target: https://scrape.do diff --git a/docs/source/modules/scrapegraphai.helpers.models_tokens.rst b/docs/source/modules/scrapegraphai.helpers.models_tokens.rst index 173e1bc3..82615b3b 100644 --- a/docs/source/modules/scrapegraphai.helpers.models_tokens.rst +++ b/docs/source/modules/scrapegraphai.helpers.models_tokens.rst @@ -19,7 +19,7 @@ Example usage: print(f"GPT-4 token limit: {gpt4_limit}") # Check the token limit for a specific model - model_name = "gpt-3.5-turbo" + model_name = "gpt-4o-mini" if model_name in models_tokens['openai']: print(f"{model_name} token limit: {models_tokens['openai'][model_name]}") else: diff --git a/docs/source/scrapers/benchmarks.rst b/docs/source/scrapers/benchmarks.rst deleted file mode 100644 index b5521ef1..00000000 --- a/docs/source/scrapers/benchmarks.rst +++ /dev/null @@ -1,23 +0,0 @@ -Benchmarks -========== - -SearchGraph -^^^^^^^^^^^ - -`SearchGraph` instantiates multiple `SmartScraperGraph` object for each URL and extract the data from the HTML. -A concurrent approach is used to speed up the process and the following table shows the time required for a scraping task with different **batch sizes**. -Only two results are taken into account. - -.. list-table:: SearchGraph - :header-rows: 1 - - * - Batch Size - - Total Time (s) - * - 1 - - 31.1 - * - 2 - - 33.52 - * - 4 - - 28.47 - * - 16 - - 21.80 diff --git a/examples/ScrapegraphAI_cookbook.ipynb b/examples/ScrapegraphAI_cookbook.ipynb new file mode 100644 index 00000000..b58bf0ea --- /dev/null +++ b/examples/ScrapegraphAI_cookbook.ipynb @@ -0,0 +1,915 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "9_CQrFgOj78b" + }, + "outputs": [], + "source": [ + "%%capture\n", + "!pip install scrapegraphai\n", + "!apt install chromium-chromedriver\n", + "!pip install nest_asyncio\n", + "!pip install playwright\n", + "!playwright install" + ] + }, + { + "cell_type": "code", + "source": [ + "import nest_asyncio\n", + "nest_asyncio.apply()" + ], + "metadata": { + "id": "tb33AcRHywFb" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "00a84YVhhxJr" + }, + "outputs": [], + "source": [ + "# correct APIKEY\n", + "OPENAI_API_KEY = \"YOUR API KEY\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For more examples visit [the examples folder](https://github.com/ScrapeGraphAI/Scrapegraph-ai/tree/main/examples)" + ], + "metadata": { + "id": "vGDjka17pqqg" + } + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Mrujgp-nlp12" + }, + "source": [ + "# SmartScraperGraph\n", + "**SmartScraperGraph** is a class representing one of the default scraping pipelines. It uses a direct graph implementation where each node has its own function, from retrieving html from a website to extracting relevant information based on your query and generate a coherent answer." + ] + }, + { + "cell_type": "markdown", + "source": [ + "![Screenshot 2024-09-19 alle 17.04.56.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA4sAAACSCAYAAADsIl+tAAABfGlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGAqSSwoyGFhYGDIzSspCnJ3UoiIjFJgv8PAzcDDIMRgxSCemFxc4BgQ4MOAE3y7xsAIoi/rgsxK8/x506a1fP4WNq+ZclYlOrj1gQF3SmpxMgMDIweQnZxSnJwLZOcA2TrJBUUlQPYMIFu3vKQAxD4BZIsUAR0IZN8BsdMh7A8gdhKYzcQCVhMS5AxkSwDZAkkQtgaInQ5hW4DYyRmJKUC2B8guiBvAgNPDRcHcwFLXkYC7SQa5OaUwO0ChxZOaFxoMcgcQyzB4MLgwKDCYMxgwWDLoMjiWpFaUgBQ65xdUFmWmZ5QoOAJDNlXBOT+3oLQktUhHwTMvWU9HwcjA0ACkDhRnEKM/B4FNZxQ7jxDLX8jAYKnMwMDcgxBLmsbAsH0PA4PEKYSYyjwGBn5rBoZt5woSixLhDmf8xkKIX5xmbARh8zgxMLDe+///sxoDA/skBoa/E////73o//+/i4H2A+PsQA4AJHdp4IxrEg8AAABWZVhJZk1NACoAAAAIAAGHaQAEAAAAAQAAABoAAAAAAAOShgAHAAAAEgAAAESgAgAEAAAAAQAAA4ugAwAEAAAAAQAAAJIAAAAAQVNDSUkAAABTY3JlZW5zaG90qcY5WgAAAdZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MTQ2PC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjkwNzwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlVzZXJDb21tZW50PlNjcmVlbnNob3Q8L2V4aWY6VXNlckNvbW1lbnQ+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgqQ4mNtAABAAElEQVR4Ae2dB3xUVfbHDyUhBZKQEAjSEqo0AVERFbB3XVesa3d17a79b++9916xobsKiF3RxYKigkjvJBAgEFJJISTA//ze8GbelIRkMpl5b+Z3Pp8wM6/cd+/3zVzeuae1qq6u2SEUEiABEiABEiABEiABEiABEiABErAQaG15z7ckQAIkQAIkQAIkQAIkQAIkQAIkYBCgssgvAgmQAAmQAAmQAAmQAAmQAAmQgB8BKot+SLiBBEiABEiABEiABEiABEiABEiAyiK/AyRAAiRAAiRAAiRAAiRAAiRAAn4EqCz6IeEGEiABEiABEiABEiABEiABEiABKov8DpAACZAACZAACZAACZAACZAACfgRoLLoh4QbSIAESIAESIAESIAESIAESIAEqCzyO0ACJEACJEACJEACJEACJEACJOBHgMqiHxJuIAESIAESIAESIAESIAESIAESoLLI7wAJkAAJkAAJkAAJkAAJkAAJkIAfASqLfki4gQRIgARIgARIgARIgARIgARIgMoivwMkQAIkQAIkQAIkQAIkQAIkQAJ+BKgs+iHhBhIgARIgARIgARIgARIgARIgASqL/A6QAAmQAAmQAAmQAAmQAAmQAAn4EaCy6IeEG0iABEiABEiABEiABEiABEiABKgs8jtAAiRAAiRAAiRAAiRAAiRAAiTgR4DKoh8SbiABEiABEiABEiABEiABEiABEqCyyO8ACZAACZAACZAACZAACZAACZCAHwEqi35IuIEESIAESIAESIAESIAESIAESIDKIr8DJEACJEACJEACJEACJEACJEACfgSoLPoh4QYSIAESIAESIAESIAESIAESIAEqi/wOkAAJkAAJkAAJkAAJkAAJkAAJ+BFo67eFG0iABEiABGxHID+vSmZOL5a5f5RK0cYaKS7cKpWVdSI7bNdVdogE/Ai0atVK2qe2lfRO8dK5a4LsuW+a7DMmQzp1aed3LDdEN4HS4lr5/acimTWjRArWbtG5rEbKy+pkx3ZOZtF956NndInJbYy5LCOznQzeM1VGjc2QnH7J0TNA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)" + ], + "metadata": { + "id": "M-dmSB0_zHCQ" + } + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uqYBNOM2YZD9" + }, + "source": [ + "## Using OpenAI models" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "ogiF4g5Z-bzG" + }, + "outputs": [], + "source": [ + "from scrapegraphai.graphs import SmartScraperGraph" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7ZzONlJ6-oe_" + }, + "source": [ + "Define the configuration for the graph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "MPZgrZ12-eRc" + }, + "outputs": [], + "source": [ + "graph_config = {\n", + " \"llm\": {\n", + " \"api_key\": OPENAI_API_KEY,\n", + " \"model\": \"openai/gpt-4o-mini\",\n", + " \"temperature\":0,\n", + " },\n", + " \"verbose\":True,\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "DjDt_10r-q8P" + }, + "source": [ + "Create the SmartScraperGraph instance and run it" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "aV4VTnx9-h_d" + }, + "outputs": [], + "source": [ + "smart_scraper_graph = SmartScraperGraph(\n", + " prompt=\"List me all the projects with their descriptions.\",\n", + " # also accepts a string with the already downloaded HTML code\n", + " source=\"https://perinim.github.io/projects/\",\n", + " config=graph_config\n", + ")" + ] + }, + { + "cell_type": "code", + "source": [ + "graph_config = {\n", + " \"llm\": {\n", + " \"api_key\": OPENAI_API_KEY,\n", + " \"model\": \"openai/gpt-4o-mini\",\n", + " },\n", + " \"verbose\": True,\n", + " \"headless\": True,\n", + "}\n", + "\n", + "# ************************************************\n", + "# Create the SmartScraperGraph instance and run it\n", + "# ************************************************\n", + "\n", + "smart_scraper_graph = SmartScraperGraph(\n", + " prompt=\"List me all the projects with their description\",\n", + " source=\"https://perinim.github.io/projects/\",\n", + " config=graph_config\n", + ")" + ], + "metadata": { + "id": "E3pyGQZLTiZ8" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Zty23idsAtwU", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "419dd75f-18c6-44d2-da82-ca8967d17e0f" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "--- Executing Fetch Node ---\n", + "--- (Fetching HTML from: https://perinim.github.io/projects/) ---\n", + "--- Executing ParseNode Node ---\n", + "--- Executing GenerateAnswer Node ---\n" + ] + } + ], + "source": [ + "result = smart_scraper_graph.run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "rnGhLGCuAqRU", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "062aeab2-3e96-4fec-d04a-b9acae142f40" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "{\n", + " \"projects\": [\n", + " {\n", + " \"name\": \"Rotary Pendulum RL\",\n", + " \"description\": \"Open Source project aimed at controlling a real life rotary pendulum using RL algorithms\"\n", + " },\n", + " {\n", + " \"name\": \"DQN Implementation from scratch\",\n", + " \"description\": \"Developed a Deep Q-Network algorithm to train a simple and double pendulum\"\n", + " },\n", + " {\n", + " \"name\": \"Multi Agents HAED\",\n", + " \"description\": \"University project which focuses on simulating a multi-agent system to perform environment mapping. Agents, equipped with sensors, explore and record their surroundings, considering uncertainties in their readings.\"\n", + " },\n", + " {\n", + " \"name\": \"Wireless ESC for Modular Drones\",\n", + " \"description\": \"Modular drone architecture proposal and proof of concept. The project received maximum grade.\"\n", + " }\n", + " ]\n", + "}\n" + ] + } + ], + "source": [ + "import json\n", + "\n", + "output = json.dumps(result, indent=2)\n", + "\n", + "line_list = output.split(\"\\n\") # Sort of line replacing \"\\n\" with a new line\n", + "\n", + "for line in line_list:\n", + " print(line)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5poLHYLVa-6E" + }, + "source": [ + "# Search graph\n", + "This graph **transforms** the user prompt in a **internet search query**, fetch the relevant URLs, and start the scraping process. Similar to the **SmartScraperGraph** but with the addition of the **SearchInternetNode** node." + ] + }, + { + "cell_type": "markdown", + "source": [ + "![image.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA9IAAAEXCAIAAADOS+unAAAgAElEQVR4Aey9h5sUVfr+/ftX3ut63+v3/a6rwHTOYTpOT8eZIa2rq2sEMaxr2KBrWMOuKypIFFBBUJKIZAYmzxDNidUVw5pWCRM6VFc6L6fu7kMzoAvszjAwT19NU91dVeecT9VU3+ep+zzn/zB6EAEiQASIABEgAkSACBABIjDCBP7PCO+fdk8EiAARIAJEgAgQASJABIgAI9lNJwERIAJEgAgQASJABIgAERhxAiS7RxwxFUAEiAARIAJEgAgQASJABEh20zlABIgAESACRIAIEAEiQARGnADJ7hFHTAUQASJABIgAESACRIAIEAGS3XQOEAEiQASIABEgAkSACBCBESdAsnvEEVMBRIAIEAEiQASIABEgAkSAZDedA0SACBABIkAEiAARIAJEYMQJkOweccRUABEgAkSACBABIkAEiAARINlN5wARIAJEgAgQASJABIgAERhxAiS7RxwxFUAEiAARIAJEgAgQASJABEh20zlABIgAESACRIAIEAEiQARGnADJ7hFHTAUQASJABIgAESACRIAIEAGS3XQOEAEiQASIABEgAkSACBCBESdAsnvEEVMBRIAIEAEiQASIABEgAkSAZDedA0SACBABIkAEiAARIAJEYMQJkOweccRUABEgAkSACBABIkAEiAARINlN5wARIAJEgAgQASJABIgAERhxAiS7RxwxFUAEiAARIAJEgAgQASJABEh20zlABIgAESACRIAIEAEiQARGnADJ7hFHTAUQASJABIgAESACRIAIEAGS3XQOEAEiQASIABEgAkSACBCBESdAsnvEEVMBRIAIEAEiQASIABEgAkSAZDedA0SACBABIkAEiAARIAJEYMQJkOweccRUABEgAkSACBABIkAEiAARINlN5wARIAJEgAgQASJABIgAERhxAiS7RxwxFUAEiAARIAJEgAgQASJABEh20zlABIgAESACRIAIEAEiQARGnADJ7hFHTAUQASJABIgAESACRIAIEAGS3XQOEAEiQASIABEgAkSACBCBESdAsnvEEVMBRIAIEAEiQASIABEgAkSAZDedA0SACPyXCaiqKssydqoaDyzrui4WNE37L5d6MexOURTGWKlUEigURRHL59QCXdcBGfvUjIfAyxgrFAp4q6qq+FzT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)" + ], + "metadata": { + "id": "NRIoaXSzzP8M" + } + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "RIvbQjyhbHhW" + }, + "outputs": [], + "source": [ + "from scrapegraphai.graphs import SearchGraph\n", + "\n", + "# Define the configuration for the graph\n", + "graph_config = {\n", + " \"llm\": {\n", + " \"api_key\": OPENAI_API_KEY,\n", + " \"model\": \"openai/gpt-4o-mini\",\n", + " \"temperature\": 0,\n", + " },\n", + "}\n", + "\n", + "# Create the SearchGraph instance\n", + "search_graph = SearchGraph(\n", + " prompt=\"List me all the European countries. Look in wikipedia.\",\n", + " config=graph_config\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "XnVtc7SzCkUY" + }, + "outputs": [], + "source": [ + "result = search_graph.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3LPAh-yQCqkY" + }, + "source": [ + "Prettify the result and display the JSON" + ] + }, + { + "cell_type": "code", + "source": [ + "import json\n", + "\n", + "output = json.dumps(result, indent=2)\n", + "\n", + "line_list = output.split(\"\\n\") # Sort of line replacing \"\\n\" with a new line\n", + "\n", + "for line in line_list:\n", + " print(line)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "xgnWDLTjzHwv", + "outputId": "f0c8ebf4-5ba5-4330-dbd8-1c9fdd93eaeb" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "{\n", + " \"European_countries\": [\n", + " \"Albania\",\n", + " \"Andorra\",\n", + " \"Armenia\",\n", + " \"Austria\",\n", + " \"Azerbaijan\",\n", + " \"Belarus\",\n", + " \"Belgium\",\n", + " \"Bosnia and Herzegovina\",\n", + " \"Bulgaria\",\n", + " \"Croatia\",\n", + " \"Cyprus\",\n", + " \"Czech Republic\",\n", + " \"Denmark\",\n", + " \"Estonia\",\n", + " \"Finland\",\n", + " \"France\",\n", + " \"Georgia\",\n", + " \"Germany\",\n", + " \"Greece\",\n", + " \"Hungary\",\n", + " \"Iceland\",\n", + " \"Ireland\",\n", + " \"Italy\",\n", + " \"Jersey\",\n", + " \"Isle of Man\",\n", + " \"Kazakhstan\",\n", + " \"Latvia\",\n", + " \"Liechtenstein\",\n", + " \"Lithuania\",\n", + " \"Luxembourg\",\n", + " \"Malta\",\n", + " \"Moldova\",\n", + " \"Monaco\",\n", + " \"Montenegro\",\n", + " \"Netherlands\",\n", + " \"North Macedonia\",\n", + " \"Norway\",\n", + " \"Poland\",\n", + " \"Portugal\",\n", + " \"Romania\",\n", + " \"Russia\",\n", + " \"San Marino\",\n", + " \"Serbia\",\n", + " \"Slovakia\",\n", + " \"Slovenia\",\n", + " \"Spain\",\n", + " \"Sweden\",\n", + " \"Switzerland\",\n", + " \"Turkey\",\n", + " \"Ukraine\",\n", + " \"United Kingdom\",\n", + " \"Vatican City\",\n", + " \"Kosovo\",\n", + " \"Gibraltar\",\n", + " \"Faroe Islands\",\n", + " \"Guernsey\",\n", + " \"Jersey\"\n", + " ],\n", + " \"sources\": [\n", + " \"https://simple.wikipedia.org/wiki/List_of_European_countries\",\n", + " \"https://en.wikipedia.org/wiki/List_of_European_countries_by_population\",\n", + " \"https://en.wikipedia.org/wiki/Member_state_of_the_European_Union\"\n", + " ]\n", + "}\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "N5IMdKHvlXFY" + }, + "source": [ + "# SpeechGraph\n", + "**SpeechGraph** is a class representing one of the default scraping pipelines that generate the answer together with an audio file. Similar to the **SmartScraperGraph** but with the addition of the **TextToSpeechNode** node.\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "![image.png](data:image/png;base64,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)" + ], + "metadata": { + "id": "pqJsEVgizs-M" + } + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "W9KhWlT3lXFd" + }, + "outputs": [], + "source": [ + "from scrapegraphai.graphs import SpeechGraph\n", + "\n", + "# Define the configuration for the graph\n", + "graph_config = {\n", + " \"llm\": {\n", + " \"api_key\": OPENAI_API_KEY,\n", + " \"model\": \"gpt-3.5-turbo\",\n", + " },\n", + " \"tts_model\": {\n", + " \"api_key\": OPENAI_API_KEY,\n", + " \"model\": \"tts-1\",\n", + " \"voice\": \"alloy\"\n", + " },\n", + " \"output_path\": \"website_summary.mp3\",\n", + "}\n", + "\n", + "# Create the SpeechGraph instance\n", + "speech_graph = SpeechGraph(\n", + " prompt=\"Create a summary of the website\",\n", + " source=\"https://perinim.github.io/projects/\",\n", + " config=graph_config,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "nVolb3paEczD", + "outputId": "d7d316a0-7580-4a6c-8f20-7e1cb1fc3f07" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "--- Executing Fetch Node ---\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Fetching pages: 100%|##########| 1/1 [00:00<00:00, 17.07it/s]\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "--- Executing Parse Node ---\n", + "--- Executing RAG Node ---\n", + "--- (updated chunks metadata) ---\n", + "--- (tokens compressed and vector stored) ---\n", + "--- Executing GenerateAnswer Node ---\n" + ] + }, + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Processing chunks: 100%|██████████| 1/1 [00:00<00:00, 339.78it/s]\n" + ] + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "--- Executing TextToSpeech Node ---\n", + "Audio saved to website_summary.mp3\n" + ] + } + ], + "source": [ + "result = speech_graph.run()\n", + "answer = result.get(\"answer\", \"No answer found\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "znt2EOKZE3z2" + }, + "source": [ + "Prettify the result and display the JSON" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "QqY0TbwbEp-O", + "outputId": "c2b1127d-0c49-4121-922e-39da65c329ee" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "{\n", + " \"summary\": {\n", + " \"title\": \"Projects | Marco Perini\",\n", + " \"projects\": [\n", + " {\n", + " \"title\": \"Rotary Pendulum RL\",\n", + " \"description\": \"Open Source project aimed at controlling a real life rotary pendulum using RL algorithms\"\n", + " },\n", + " {\n", + " \"title\": \"DQN Implementation from scratch\",\n", + " \"description\": \"Developed a Deep Q-Network algorithm to train a simple and double pendulum\"\n", + " },\n", + " {\n", + " \"title\": \"Multi Agents HAED\",\n", + " \"description\": \"University project which focuses on simulating a multi-agent system to perform environment mapping. Agents, equipped with sensors, explore and record their surroundings, considering uncertainties in their readings.\"\n", + " },\n", + " {\n", + " \"title\": \"Wireless ESC for Modular Drones\",\n", + " \"description\": \"Modular drone architecture proposal and proof of concept. The project received maximum grade.\"\n", + " }\n", + " ]\n", + " }\n", + "}\n" + ] + } + ], + "source": [ + "import json\n", + "\n", + "output = json.dumps(answer, indent=2)\n", + "\n", + "line_list = output.split(\"\\n\") # Sort of line replacing \"\\n\" with a new line\n", + "\n", + "for line in line_list:\n", + " print(line)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 75 + }, + "id": "lfJ_jVwklXFd", + "outputId": "dc4ad491-4422-4edb-91ae-35775b23168a" + }, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + " \n", + " " + ] + }, + "metadata": {} + } + ], + "source": [ + "from IPython.display import Audio\n", + "wn = Audio(\"website_summary.mp3\", autoplay=True)\n", + "display(wn)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "p9kC0x4NuLTx" + }, + "source": [ + "# Build a Custom Graph\n", + "It is possible to **build your own scraping pipeline** by using the default nodes and place them as you wish, without using pre-defined graphs." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Pr6DIqt2uLUI" + }, + "source": [ + "You can create **custom graphs** based on your necessities, using standard nodes provided by the library.\n", + "\n", + "The list of the existing nodes can be found through the *nodes_metadata* json construct.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "-o29vDSIvG4t", + "outputId": "be469b65-ba01-437a-e217-ed1c4f3ad264" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "dict_keys(['SearchInternetNode', 'FetchNode', 'GetProbableTagsNode', 'ParseNode', 'RAGNode', 'GenerateAnswerNode', 'ConditionalNode', 'ImageToTextNode', 'TextToSpeechNode'])" + ] + }, + "metadata": {}, + "execution_count": 17 + } + ], + "source": [ + "# check available nodes\n", + "from scrapegraphai.helpers import nodes_metadata\n", + "\n", + "nodes_metadata.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "829wW5E6vrjJ", + "outputId": "58203025-64ce-4107-f6d3-3b3cfa5537d5" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "{'description': 'Converts image content to text by \\n extracting visual information and interpreting it.',\n", + " 'type': 'node',\n", + " 'args': {'image_data': 'Data of the image to be processed.'},\n", + " 'returns': \"Updated state with the textual description of the image under 'image_text' key.\"}" + ] + }, + "metadata": {}, + "execution_count": 18 + } + ], + "source": [ + "# to get more information about a node\n", + "nodes_metadata['ImageToTextNode']" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3pnNFDckwWy7" + }, + "source": [ + "To create a custom graph we must:\n", + "\n", + "1. **Istantiate the nodes** you want to use\n", + "2. Create the graph using **BaseGraph** class, which must have a **list of nodes**, tuples representing the **edges** of the graph, an **entry_point**\n", + "3. Run it using the **execute** method\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "eQLZJyg4uLUJ" + }, + "outputs": [], + "source": [ + "from langchain_openai import OpenAIEmbeddings\n", + "from scrapegraphai.models import OpenAI\n", + "from scrapegraphai.graphs import BaseGraph\n", + "from scrapegraphai.nodes import FetchNode, ParseNode, RAGNode, GenerateAnswerNode\n", + "\n", + "# Define the configuration for the graph\n", + "graph_config = {\n", + " \"llm\": {\n", + " \"api_key\": OPENAI_API_KEY,\n", + " \"model\": \"openai/gpt-4o\",\n", + " \"temperature\": 0,\n", + " \"streaming\": True\n", + " },\n", + "}\n", + "\n", + "llm_model = OpenAI(graph_config[\"llm\"])\n", + "embedder = OpenAIEmbeddings(api_key=llm_model.openai_api_key)\n", + "\n", + "# define the nodes for the graph\n", + "fetch_node = FetchNode(\n", + " input=\"url | local_dir\",\n", + " output=[\"doc\", \"link_urls\", \"img_urls\"],\n", + " node_config={\n", + " \"verbose\": True,\n", + " \"headless\": True,\n", + " }\n", + ")\n", + "parse_node = ParseNode(\n", + " input=\"doc\",\n", + " output=[\"parsed_doc\"],\n", + " node_config={\n", + " \"chunk_size\": 4096,\n", + " \"verbose\": True,\n", + " }\n", + ")\n", + "rag_node = RAGNode(\n", + " input=\"user_prompt & (parsed_doc | doc)\",\n", + " output=[\"relevant_chunks\"],\n", + " node_config={\n", + " \"llm_model\": llm_model,\n", + " \"embedder_model\": embedder,\n", + " \"verbose\": True,\n", + " }\n", + ")\n", + "generate_answer_node = GenerateAnswerNode(\n", + " input=\"user_prompt & (relevant_chunks | parsed_doc | doc)\",\n", + " output=[\"answer\"],\n", + " node_config={\n", + " \"llm_model\": llm_model,\n", + " \"verbose\": True,\n", + " }\n", + ")\n", + "\n", + "# create the graph by defining the nodes and their connections\n", + "graph = BaseGraph(\n", + " nodes=[\n", + " fetch_node,\n", + " parse_node,\n", + " rag_node,\n", + " generate_answer_node,\n", + " ],\n", + " edges=[\n", + " (fetch_node, parse_node),\n", + " (parse_node, rag_node),\n", + " (rag_node, generate_answer_node)\n", + " ],\n", + " entry_point=fetch_node\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5FYKF9H1Fvb8", + "outputId": "666d51fe-5e2f-4398-a3b0-bb820960a0d1" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--- Executing Fetch Node ---\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Fetching pages: 100%|##########| 1/1 [00:00<00:00, 28.65it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "--- Executing Parse Node ---\n", + "--- Executing RAG Node ---\n", + "--- (updated chunks metadata) ---\n", + "--- (tokens compressed and vector stored) ---\n", + "--- Executing GenerateAnswer Node ---\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Processing chunks: 100%|██████████| 1/1 [00:00<00:00, 911.01it/s]\n" + ] + } + ], + "source": [ + "# execute the graph\n", + "result, execution_info = graph.execute({\n", + " \"user_prompt\": \"List me the projects with their description\",\n", + " \"url\": \"https://perinim.github.io/projects/\"\n", + "})\n", + "\n", + "# get the answer from the result\n", + "result = result.get(\"answer\", \"No answer found.\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "JEP8_zZ9GHW2" + }, + "source": [ + "Prettify the result and display the JSON" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "nx9qGaxvFmfT", + "outputId": "fb327a6a-0dfa-417b-8dbb-505bebc96fe8" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"projects\": [\n", + " {\n", + " \"title\": \"Rotary Pendulum RL\",\n", + " \"description\": \"Open Source project aimed at controlling a real life rotary pendulum using RL algorithms\"\n", + " },\n", + " {\n", + " \"title\": \"DQN Implementation from scratch\",\n", + " \"description\": \"Developed a Deep Q-Network algorithm to train a simple and double pendulum\"\n", + " },\n", + " {\n", + " \"title\": \"Multi Agents HAED\",\n", + " \"description\": \"University project which focuses on simulating a multi-agent system to perform environment mapping. Agents, equipped with sensors, explore and record their surroundings, considering uncertainties in their readings.\"\n", + " },\n", + " {\n", + " \"title\": \"Wireless ESC for Modular Drones\",\n", + " \"description\": \"Modular drone architecture proposal and proof of concept. The project received maximum grade.\"\n", + " }\n", + " ]\n", + "}\n" + ] + } + ], + "source": [ + "import json\n", + "\n", + "output = json.dumps(result, indent=2)\n", + "\n", + "line_list = output.split(\"\\n\") # Sort of line replacing \"\\n\" with a new line\n", + "\n", + "for line in line_list:\n", + " print(line)" + ] + } + ], + "metadata": { + "colab": { + "collapsed_sections": [ + "N5IMdKHvlXFY" + ], + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/examples/anthropic/.env.example b/examples/anthropic/.env.example deleted file mode 100644 index 2789e380..00000000 --- a/examples/anthropic/.env.example +++ /dev/null @@ -1 +0,0 @@ -ANTHROPIC_API_KEY="YOUR ANTHROPIC API KEY" \ No newline at end of file diff --git a/examples/anthropic/code_generator_graph_anthropic.py b/examples/anthropic/code_generator_graph_anthropic.py deleted file mode 100644 index 71160b8c..00000000 --- a/examples/anthropic/code_generator_graph_anthropic.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os, json -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -anthropic_key = os.getenv("ANTHROPIC_API_KEY") - -graph_config = { - "llm": { - "api_key":anthropic_key, - "model": "anthropic/claude-3-haiku-20240307", - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) diff --git a/examples/anthropic/csv_scraper_anthropic.py b/examples/anthropic/csv_scraper_anthropic.py deleted file mode 100644 index 4fd5aaaf..00000000 --- a/examples/anthropic/csv_scraper_anthropic.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r') as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -# required environment variables in .env -# HUGGINGFACEHUB_API_TOKEN -# ANTHROPIC_API_KEY -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=text, # Pass the content of the file - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) \ No newline at end of file diff --git a/examples/anthropic/csv_scraper_graph_multi_anthropic.py b/examples/anthropic/csv_scraper_graph_multi_anthropic.py deleted file mode 100644 index ed0bcbc5..00000000 --- a/examples/anthropic/csv_scraper_graph_multi_anthropic.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r') as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/anthropic/custom_graph_anthropic.py b/examples/anthropic/custom_graph_anthropic.py deleted file mode 100644 index 6df51108..00000000 --- a/examples/anthropic/custom_graph_anthropic.py +++ /dev/null @@ -1,94 +0,0 @@ -""" -Example of custom graph using existing nodes -""" -import os -from dotenv import load_dotenv -from langchain_anthropic import ChatAnthropic -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import FetchNode, ParseNode, GenerateAnswerNode, RobotsNode -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = ChatAnthropic(graph_config["llm"]) - -# define the nodes for the graph -robot_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={ - "llm_model": llm_model, - "force_scraping": True, - "verbose": True, - } -) - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "verbose": True, - "headless": True, - } -) -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={ - "chunk_size": 4096, - "verbose": True, - } -) -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={ - "llm_model": llm_model, - "verbose": True, - } -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes=[ - robot_node, - fetch_node, - parse_node, - generate_answer_node, - ], - edges=[ - (robot_node, fetch_node), - (fetch_node, parse_node), - (parse_node, generate_answer_node) - ], - entry_point=robot_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "Describe the content", - "url": "https://example.com/" -}) - -# get the answer from the result -result = result.get("answer", "No answer found.") -print(result) diff --git a/examples/anthropic/depth_search_graph_anthropic.py b/examples/anthropic/depth_search_graph_anthropic.py deleted file mode 100644 index 565934ed..00000000 --- a/examples/anthropic/depth_search_graph_anthropic.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/anthropic/document_scraper_anthropic.py b/examples/anthropic/document_scraper_anthropic.py deleted file mode 100644 index a8f253be..00000000 --- a/examples/anthropic/document_scraper_anthropic.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - } -} - - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/anthropic/json_scraper_anthropic.py b/examples/anthropic/json_scraper_anthropic.py deleted file mode 100644 index fd5aa4e8..00000000 --- a/examples/anthropic/json_scraper_anthropic.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - } -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/anthropic/json_scraper_multi_anthropic.py b/examples/anthropic/json_scraper_multi_anthropic.py deleted file mode 100644 index d016439d..00000000 --- a/examples/anthropic/json_scraper_multi_anthropic.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Module for showing how JSONScraperMultiGraph multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/anthropic/rate_limit_anthropic.py b/examples/anthropic/rate_limit_anthropic.py deleted file mode 100644 index f9321770..00000000 --- a/examples/anthropic/rate_limit_anthropic.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper while setting an API rate limit. -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - - -# required environment variables in .env -# ANTHROPIC_API_KEY -load_dotenv() - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - "rate_limit": { - "requests_per_second": 1 - } - }, -} - -smart_scraper_graph = SmartScraperGraph( - prompt="""Don't say anything else. Output JSON only. List me all the events, with the following fields: company_name, event_name, event_start_date, event_start_time, - event_end_date, event_end_time, location, event_mode, event_category, - third_party_redirect, no_of_days, - time_in_hours, hosted_or_attending, refreshments_type, - registration_available, registration_link""", - # also accepts a string with the already downloaded HTML code - source="https://www.hmhco.com/event", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/anthropic/scrape_plain_text_anthropic.py b/examples/anthropic/scrape_plain_text_anthropic.py deleted file mode 100644 index fd8ebd1d..00000000 --- a/examples/anthropic/scrape_plain_text_anthropic.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/anthropic/script_generator_anthropic.py b/examples/anthropic/script_generator_anthropic.py deleted file mode 100644 index 8c9333e1..00000000 --- a/examples/anthropic/script_generator_anthropic.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/anthropic/script_multi_generator_anthropic.py b/examples/anthropic/script_multi_generator_anthropic.py deleted file mode 100644 index d47e60e9..00000000 --- a/examples/anthropic/script_multi_generator_anthropic.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/anthropic/search_graph_anthropic.py b/examples/anthropic/search_graph_anthropic.py deleted file mode 100644 index 0e1d7b45..00000000 --- a/examples/anthropic/search_graph_anthropic.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/anthropic/search_graph_schema_anthropic.py b/examples/anthropic/search_graph_schema_anthropic.py deleted file mode 100644 index 926e72ea..00000000 --- a/examples/anthropic/search_graph_schema_anthropic.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Example of Search Graph -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SearchGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) diff --git a/examples/anthropic/search_link_graph_anthropic.py b/examples/anthropic/search_link_graph_anthropic.py deleted file mode 100644 index 70798cf3..00000000 --- a/examples/anthropic/search_link_graph_anthropic.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -from langchain_openai import AzureChatOpenAI -from langchain_openai import AzureOpenAIEmbeddings - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/anthropic/smart_scraper_anthropic.py b/examples/anthropic/smart_scraper_anthropic.py deleted file mode 100644 index 7eb655d5..00000000 --- a/examples/anthropic/smart_scraper_anthropic.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper using Azure OpenAI Key -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -smart_scraper_graph = SmartScraperGraph( - prompt="""Don't say anything else. Output JSON only. List me all the events, with the following fields: company_name, event_name, event_start_date, event_start_time, - event_end_date, event_end_time, location, event_mode, event_category, - third_party_redirect, no_of_days, - time_in_hours, hosted_or_attending, refreshments_type, - registration_available, registration_link""", - # also accepts a string with the already downloaded HTML code - source="https://www.hmhco.com/event", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/anthropic/smart_scraper_lite_anthropic.py b/examples/anthropic/smart_scraper_lite_anthropic.py deleted file mode 100644 index 698623c6..00000000 --- a/examples/anthropic/smart_scraper_lite_anthropic.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/anthropic/smart_scraper_multi_anthropic.py b/examples/anthropic/smart_scraper_multi_anthropic.py deleted file mode 100644 index e4dc0aca..00000000 --- a/examples/anthropic/smart_scraper_multi_anthropic.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/anthropic/smart_scraper_multi_concat_anthropic.py b/examples/anthropic/smart_scraper_multi_concat_anthropic.py deleted file mode 100644 index d5c65a14..00000000 --- a/examples/anthropic/smart_scraper_multi_concat_anthropic.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/anthropic/smart_scraper_multi_lite_anthropic.py b/examples/anthropic/smart_scraper_multi_lite_anthropic.py deleted file mode 100644 index 7cf3c09d..00000000 --- a/examples/anthropic/smart_scraper_multi_lite_anthropic.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/anthropic/smart_scraper_schema_anthropic.py b/examples/anthropic/smart_scraper_schema_anthropic.py deleted file mode 100644 index 3cebd257..00000000 --- a/examples/anthropic/smart_scraper_schema_anthropic.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper using Azure OpenAI Key -""" -import os -from typing import List -from pydantic import BaseModel, Field -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - schema=Projects, - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/anthropic/xml_scraper_anthropic.py b/examples/anthropic/xml_scraper_anthropic.py deleted file mode 100644 index 5568f0a3..00000000 --- a/examples/anthropic/xml_scraper_anthropic.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/anthropic/xml_scraper_graph_multi_anthropic.py b/examples/anthropic/xml_scraper_graph_multi_anthropic.py deleted file mode 100644 index 577e2e1d..00000000 --- a/examples/anthropic/xml_scraper_graph_multi_anthropic.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/azure/code_generator_graph_azure.py b/examples/azure/code_generator_graph_azure.py deleted file mode 100644 index 7dc13602..00000000 --- a/examples/azure/code_generator_graph_azure.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) diff --git a/examples/azure/csv_scraper_azure.py b/examples/azure/csv_scraper_azure.py deleted file mode 100644 index 5bc9ca50..00000000 --- a/examples/azure/csv_scraper_azure.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/azure/csv_scraper_graph_multi_azure.py b/examples/azure/csv_scraper_graph_multi_azure.py deleted file mode 100644 index 0c599427..00000000 --- a/examples/azure/csv_scraper_graph_multi_azure.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/azure/depth_search_graph_azure.py b/examples/azure/depth_search_graph_azure.py deleted file mode 100644 index 96ccc23e..00000000 --- a/examples/azure/depth_search_graph_azure.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -depth_search_graph_azure example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o", - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/azure/document_scraper_azure.py b/examples/azure/document_scraper_azure.py deleted file mode 100644 index 43f00678..00000000 --- a/examples/azure/document_scraper_azure.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/azure/json_scraper_azure.py b/examples/azure/json_scraper_azure.py deleted file mode 100644 index 5224f9bb..00000000 --- a/examples/azure/json_scraper_azure.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper using Azure OpenAI Key -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Initialize the model instances -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -smart_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/azure/json_scraper_multi_azure.py b/examples/azure/json_scraper_multi_azure.py deleted file mode 100644 index 93ac02e3..00000000 --- a/examples/azure/json_scraper_multi_azure.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Module for showing how JSONScraperMultiGraph multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/azure/rate_limit_azure.py b/examples/azure/rate_limit_azure.py deleted file mode 100644 index aa0f943d..00000000 --- a/examples/azure/rate_limit_azure.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - - -# required environment variable in .env -# AZURE_OPENAI_ENDPOINT -# AZURE_OPENAI_CHAT_DEPLOYMENT_NAME -# MODEL_NAME -# AZURE_OPENAI_API_KEY -# OPENAI_API_TYPE -# AZURE_OPENAI_API_VERSION -# AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT_NAME -load_dotenv() - - -# ************************************************ -# Initialize the model instances -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o", - "rate_limit": { - "requests_per_second": 1 - }, - }, - "verbose": True, - "headless": False -} - -smart_scraper_graph = SmartScraperGraph( - prompt="""List me all the events, with the following fields: company_name, event_name, event_start_date, event_start_time, - event_end_date, event_end_time, location, event_mode, event_category, - third_party_redirect, no_of_days, - time_in_hours, hosted_or_attending, refreshments_type, - registration_available, registration_link""", - # also accepts a string with the already downloaded HTML code - source="https://www.hmhco.com/event", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/azure/scrape_plain_text_azure.py b/examples/azure/scrape_plain_text_azure.py deleted file mode 100644 index 0beb1526..00000000 --- a/examples/azure/scrape_plain_text_azure.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/azure/script_generator_azure.py b/examples/azure/script_generator_azure.py deleted file mode 100644 index 5eb40b1c..00000000 --- a/examples/azure/script_generator_azure.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/azure/script_multi_generator_azure.py b/examples/azure/script_multi_generator_azure.py deleted file mode 100644 index 6bb94051..00000000 --- a/examples/azure/script_multi_generator_azure.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/azure/search_graph_azure.py b/examples/azure/search_graph_azure.py deleted file mode 100644 index 8c7d9a9e..00000000 --- a/examples/azure/search_graph_azure.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -load_dotenv() - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Initialize the model instances -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/azure/search_graph_schema_azure.py b/examples/azure/search_graph_schema_azure.py deleted file mode 100644 index bc22f7bc..00000000 --- a/examples/azure/search_graph_schema_azure.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Example of Search Graph -""" -import os -from typing import List -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -from pydantic import BaseModel, Field - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/azure/search_link_graph_azure.py b/examples/azure/search_link_graph_azure.py deleted file mode 100644 index 42ed07ad..00000000 --- a/examples/azure/search_link_graph_azure.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/azure/smart_scraper_azure.py b/examples/azure/smart_scraper_azure.py deleted file mode 100644 index 11643a6d..00000000 --- a/examples/azure/smart_scraper_azure.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper using Azure OpenAI Key -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Initialize the model instances -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -smart_scraper_graph = SmartScraperGraph( - prompt="""List me all the events, with the following fields: - company_name, event_name, event_start_date, event_start_time, - event_end_date, event_end_time, location, event_mode, event_category, - third_party_redirect, no_of_days, - time_in_hours, hosted_or_attending, refreshments_type, - registration_available, registration_link""", - # also accepts a string with the already downloaded HTML code - source="https://www.hmhco.com/event", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/azure/smart_scraper_lite_azure.py b/examples/azure/smart_scraper_lite_azure.py deleted file mode 100644 index 335c4832..00000000 --- a/examples/azure/smart_scraper_lite_azure.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/azure/smart_scraper_multi_azure.py b/examples/azure/smart_scraper_multi_azure.py deleted file mode 100644 index e066eaf1..00000000 --- a/examples/azure/smart_scraper_multi_azure.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/azure/smart_scraper_multi_concat_azure.py b/examples/azure/smart_scraper_multi_concat_azure.py deleted file mode 100644 index 072cb190..00000000 --- a/examples/azure/smart_scraper_multi_concat_azure.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/azure/smart_scraper_multi_lite_azure.py b/examples/azure/smart_scraper_multi_lite_azure.py deleted file mode 100644 index b9046d9f..00000000 --- a/examples/azure/smart_scraper_multi_lite_azure.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/azure/smart_scraper_schema_azure.py b/examples/azure/smart_scraper_schema_azure.py deleted file mode 100644 index 28d8b87e..00000000 --- a/examples/azure/smart_scraper_schema_azure.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" -import os -import json -from typing import List -from pydantic import BaseModel, Field -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Initialize the model instances -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/azure/xml_scraper_azure.py b/examples/azure/xml_scraper_azure.py deleted file mode 100644 index cd53242c..00000000 --- a/examples/azure/xml_scraper_azure.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper using Azure OpenAI Key -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - - -# ************************************************ -# Initialize the model instances -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o" - }, - "verbose": True, - "headless": False -} - -smart_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/azure/xml_scraper_graph_multi_azure.py b/examples/azure/xml_scraper_graph_multi_azure.py deleted file mode 100644 index e7aaf382..00000000 --- a/examples/azure/xml_scraper_graph_multi_azure.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "api_key": os.environ["AZURE_OPENAI_KEY"], - "model": "azure_openai/gpt-4o", - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/bedrock/.env.example b/examples/bedrock/.env.example deleted file mode 100644 index cd27769e..00000000 --- a/examples/bedrock/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -AWS_ACCESS_KEY_ID="..." -AWS_SECRET_ACCESS_KEY="..." -AWS_SESSION_TOKEN="..." -AWS_DEFAULT_REGION="..." \ No newline at end of file diff --git a/examples/bedrock/README.md b/examples/bedrock/README.md deleted file mode 100644 index 88edd82c..00000000 --- a/examples/bedrock/README.md +++ /dev/null @@ -1,3 +0,0 @@ -This folder contains examples of how to use ScrapeGraphAI with [Amazon Bedrock](https://aws.amazon.com/bedrock/) ⛰️. The examples show how to extract information from websites and files using a natural language prompt. - -![](scrapegraphai_bedrock.png) \ No newline at end of file diff --git a/examples/bedrock/code_generator_graph_bedrock.py b/examples/bedrock/code_generator_graph_bedrock.py deleted file mode 100644 index 7a0561fe..00000000 --- a/examples/bedrock/code_generator_graph_bedrock.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" - -import os, json -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) \ No newline at end of file diff --git a/examples/bedrock/csv_scraper_bedrock.py b/examples/bedrock/csv_scraper_bedrock.py deleted file mode 100644 index cf453ab3..00000000 --- a/examples/bedrock/csv_scraper_bedrock.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" - -import os -import json - -from dotenv import load_dotenv - -import pandas as pd - -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(json.dumps(result, indent=4)) - diff --git a/examples/bedrock/csv_scraper_graph_multi_bedrock.py b/examples/bedrock/csv_scraper_graph_multi_bedrock.py deleted file mode 100644 index b9dd7f6f..00000000 --- a/examples/bedrock/csv_scraper_graph_multi_bedrock.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" - -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/bedrock/custom_graph_bedrock.py b/examples/bedrock/custom_graph_bedrock.py deleted file mode 100644 index d72f6999..00000000 --- a/examples/bedrock/custom_graph_bedrock.py +++ /dev/null @@ -1,125 +0,0 @@ -""" -Example of custom graph using existing nodes -""" - -import json - -from dotenv import load_dotenv - -from langchain_aws import BedrockEmbeddings -from scrapegraphai.models import Bedrock -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import ( - FetchNode, - ParseNode, - RAGNode, - GenerateAnswerNode, - RobotsNode -) - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = Bedrock({ - 'model_id': graph_config["llm"]["model"].split("/")[-1], - 'model_kwargs': { - 'temperature': 0.0 - }}) -embedder = BedrockEmbeddings(model_id=graph_config["embeddings"]["model"].split("/")[-1]) - -# Define the nodes for the graph -robot_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={ - "llm_model": llm_model, - "force_scraping": True, - "verbose": True, - } -) - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "verbose": True, - "headless": True, - } -) - -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={ - "chunk_size": 4096, - "verbose": True, - } -) - -rag_node = RAGNode( - input="user_prompt & (parsed_doc | doc)", - output=["relevant_chunks"], - node_config={ - "llm_model": llm_model, - "embedder_model": embedder, - "verbose": True, - } -) - -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={ - "llm_model": llm_model, - "verbose": True, - } -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes=[ - robot_node, - fetch_node, - parse_node, - rag_node, - generate_answer_node, - ], - edges=[ - (robot_node, fetch_node), - (fetch_node, parse_node), - (parse_node, rag_node), - (rag_node, generate_answer_node) - ], - entry_point=robot_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "List me all the articles", - "url": "https://perinim.github.io/projects" -}) - -# Get the answer from the result -result = result.get("answer", "No answer found.") -print(json.dumps(result, indent=4)) diff --git a/examples/bedrock/depth_search_graph_bedrock.py b/examples/bedrock/depth_search_graph_bedrock.py deleted file mode 100644 index 243547a4..00000000 --- a/examples/bedrock/depth_search_graph_bedrock.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -depth_search_graph_opeani example -""" -from scrapegraphai.graphs import DepthSearchGraph - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/bedrock/document_scraper_bedrock.py b/examples/bedrock/document_scraper_bedrock.py deleted file mode 100644 index f9b99e1f..00000000 --- a/examples/bedrock/document_scraper_bedrock.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/bedrock/inputs/books.xml b/examples/bedrock/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/bedrock/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/bedrock/inputs/example.json b/examples/bedrock/inputs/example.json deleted file mode 100644 index d729b76a..00000000 --- a/examples/bedrock/inputs/example.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "quiz": { - "sport": { - "q1": { - "question": "Which one is correct team name in NBA?", - "options": [ - "New York Bulls", - "Los Angeles Kings", - "Golden State Warriros", - "Huston Rocket" - ], - "answer": "Huston Rocket" - } - }, - "maths": { - "q1": { - "question": "5 + 7 = ?", - "options": [ - "10", - "11", - "12", - "13" - ], - "answer": "12" - }, - "q2": { - "question": "12 - 8 = ?", - "options": [ - "1", - "2", - "3", - "4" - ], - "answer": "4" - } - } - } -} \ No newline at end of file diff --git a/examples/bedrock/inputs/username.csv b/examples/bedrock/inputs/username.csv deleted file mode 100644 index 8c039d7e..00000000 --- a/examples/bedrock/inputs/username.csv +++ /dev/null @@ -1,6 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith \ No newline at end of file diff --git a/examples/bedrock/json_scraper_bedrock.py b/examples/bedrock/json_scraper_bedrock.py deleted file mode 100644 index c34cb1bd..00000000 --- a/examples/bedrock/json_scraper_bedrock.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all questions and options in the math section, no answers.", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = json_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/bedrock/json_scraper_multi_bedrock.py b/examples/bedrock/json_scraper_multi_bedrock.py deleted file mode 100644 index 5848ef17..00000000 --- a/examples/bedrock/json_scraper_multi_bedrock.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Module for showing how JSONScraperMultiGraph multi works -""" -import os -import json -from scrapegraphai.graphs import JSONScraperMultiGraph - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/bedrock/rate_limit_bedrock.py b/examples/bedrock/rate_limit_bedrock.py deleted file mode 100644 index 98e2e3db..00000000 --- a/examples/bedrock/rate_limit_bedrock.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0, - "rate_limit": { - "requests_per_second": 1 - }, - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/bedrock/scrape_plain_text_bedrock.py b/examples/bedrock/scrape_plain_text_bedrock.py deleted file mode 100644 index 1a89786e..00000000 --- a/examples/bedrock/scrape_plain_text_bedrock.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/bedrock/scrapegraphai_bedrock.png b/examples/bedrock/scrapegraphai_bedrock.png deleted file mode 100644 index 918cf191..00000000 Binary files a/examples/bedrock/scrapegraphai_bedrock.png and /dev/null differ diff --git a/examples/bedrock/script_generator_bedrock.py b/examples/bedrock/script_generator_bedrock.py deleted file mode 100644 index 4adb13f1..00000000 --- a/examples/bedrock/script_generator_bedrock.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/bedrock/script_multi_generator_bedrock.py b/examples/bedrock/script_multi_generator_bedrock.py deleted file mode 100644 index 2491a1f9..00000000 --- a/examples/bedrock/script_multi_generator_bedrock.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/bedrock/search_graph_bedrock.py b/examples/bedrock/search_graph_bedrock.py deleted file mode 100644 index 6369f647..00000000 --- a/examples/bedrock/search_graph_bedrock.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -Example of Search Graph -""" -from scrapegraphai.graphs import SearchGraph - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/bedrock/search_graph_schema_bedrock.py b/examples/bedrock/search_graph_schema_bedrock.py deleted file mode 100644 index 55ad772c..00000000 --- a/examples/bedrock/search_graph_schema_bedrock.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Example of Search Graph -""" -from typing import List -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/bedrock/search_link_graph_bedrock.py b/examples/bedrock/search_link_graph_bedrock.py deleted file mode 100644 index 64e62710..00000000 --- a/examples/bedrock/search_link_graph_bedrock.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Example of Search Graph -""" -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/bedrock/smart_scraper_bedrock.py b/examples/bedrock/smart_scraper_bedrock.py deleted file mode 100644 index d63f1ece..00000000 --- a/examples/bedrock/smart_scraper_bedrock.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/bedrock/smart_scraper_lite_bedrock.py b/examples/bedrock/smart_scraper_lite_bedrock.py deleted file mode 100644 index 2bf0471c..00000000 --- a/examples/bedrock/smart_scraper_lite_bedrock.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import json -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/bedrock/smart_scraper_multi_bedrock.py b/examples/bedrock/smart_scraper_multi_bedrock.py deleted file mode 100644 index 9de097b0..00000000 --- a/examples/bedrock/smart_scraper_multi_bedrock.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import json -from scrapegraphai.graphs import SmartScraperMultiGraph - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/bedrock/smart_scraper_multi_concat_bedrock.py b/examples/bedrock/smart_scraper_multi_concat_bedrock.py deleted file mode 100644 index 74c30a3f..00000000 --- a/examples/bedrock/smart_scraper_multi_concat_bedrock.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import json -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/bedrock/smart_scraper_multi_lite_bedrock.py b/examples/bedrock/smart_scraper_multi_lite_bedrock.py deleted file mode 100644 index 5cb26067..00000000 --- a/examples/bedrock/smart_scraper_multi_lite_bedrock.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import json -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/bedrock/smart_scraper_schema_bedrock.py b/examples/bedrock/smart_scraper_schema_bedrock.py deleted file mode 100644 index 2829efec..00000000 --- a/examples/bedrock/smart_scraper_schema_bedrock.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -from typing import List -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/bedrock/xml_scraper_bedrock.py b/examples/bedrock/xml_scraper_bedrock.py deleted file mode 100644 index 2110fc9f..00000000 --- a/examples/bedrock/xml_scraper_bedrock.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" - -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - }, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books. Skip the preamble.", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/bedrock/xml_scraper_graph_multi_bedrock.py b/examples/bedrock/xml_scraper_graph_multi_bedrock.py deleted file mode 100644 index ab7bd4ad..00000000 --- a/examples/bedrock/xml_scraper_graph_multi_bedrock.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "client": "client_name", - "model": "bedrock/anthropic.claude-3-sonnet-20240229-v1:0", - "temperature": 0.0 - }, -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/benchmarks/GenerateScraper/.env.example b/examples/benchmarks/GenerateScraper/.env.example deleted file mode 100644 index 599a2397..00000000 --- a/examples/benchmarks/GenerateScraper/.env.example +++ /dev/null @@ -1 +0,0 @@ -OPENAI_APIKEY="your openai key here" \ No newline at end of file diff --git a/examples/benchmarks/GenerateScraper/Readme.md b/examples/benchmarks/GenerateScraper/Readme.md deleted file mode 100644 index 79201d22..00000000 --- a/examples/benchmarks/GenerateScraper/Readme.md +++ /dev/null @@ -1,43 +0,0 @@ -# Local models -# Local models -The two websites benchmark are: -- Example 1: https://perinim.github.io/projects -- Example 2: https://www.wired.com (at 17/4/2024) - -Both are strored locally as txt file in .txt format because in this way we do not have to think about the internet connection - -The time is measured in seconds - -The model runned for this benchmark is Mistral on Ollama with nomic-embed-text - -| Hardware | Model | Example 1 | Example 2 | -| ---------------------- | --------------------------------------- | --------- | --------- | -| Macbook 14' m1 pro | Mistral on Ollama with nomic-embed-text | 30.54s | 35.76s | -| Macbook m2 max | Mistral on Ollama with nomic-embed-text | | | -| Macbook 14' m1 pro
| Llama3 on Ollama with nomic-embed-text | 27.82s | 29.986s | -| Macbook m2 max
| Llama3 on Ollama with nomic-embed-text | | | - - -**Note**: the examples on Docker are not runned on other devices than the Macbook because the performance are to slow (10 times slower than Ollama). -# Performance on APIs services -### Example 1: personal portfolio -**URL**: https://perinim.github.io/projects -**Task**: List me all the projects with their description. - -| Name | Execution time (seconds) | total_tokens | prompt_tokens | completion_tokens | successful_requests | total_cost_USD | -| --------------------------- | ------------------------ | ------------ | ------------- | ----------------- | ------------------- | -------------- | -| gpt-3.5-turbo | 24.21 | 1892 | 1802 | 90 | 1 | 0.002883 | -| gpt-4-turbo-preview | 6.614 | 1936 | 1802 | 134 | 1 | 0.02204 | -| Grooq with nomic-embed-text | 6.71 | 2201 | 2024 | 177 | 1 | 0 | - -### Example 2: Wired -**URL**: https://www.wired.com -**Task**: List me all the articles with their description. - -| Name | Execution time (seconds) | total_tokens | prompt_tokens | completion_tokens | successful_requests | total_cost_USD | -| --------------------------- | ------------------------ | ------------ | ------------- | ----------------- | ------------------- | -------------- | -| gpt-3.5-turbo | | | | | | | -| gpt-4-turbo-preview | | | | | | | -| Grooq with nomic-embed-text | | | | | | | - - diff --git a/examples/benchmarks/GenerateScraper/benchmark_docker.py b/examples/benchmarks/GenerateScraper/benchmark_docker.py deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/benchmarks/GenerateScraper/benchmark_groq.py b/examples/benchmarks/GenerateScraper/benchmark_groq.py deleted file mode 100644 index bef4e8b6..00000000 --- a/examples/benchmarks/GenerateScraper/benchmark_groq.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "embeddings": { - "model": "ollama/nomic-embed-text", - "temperature": 0, - "base_url": "http://localhost:11434", # set ollama URL arbitrarily - }, - "headless": False, - "library": "beautifoulsoup" -} - - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = ScriptCreatorGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/GenerateScraper/benchmark_llama3.py b/examples/benchmarks/GenerateScraper/benchmark_llama3.py deleted file mode 100644 index a80b2e71..00000000 --- a/examples/benchmarks/GenerateScraper/benchmark_llama3.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Read the text file -# ************************************************ -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "model": "ollama/llama3", - "temperature": 0, - # "model_tokens": 2000, # set context length arbitrarily, - "base_url": "http://localhost:11434", # set ollama URL arbitrarily - }, - "embeddings": { - "model": "ollama/nomic-embed-text", - "temperature": 0, - "base_url": "http://localhost:11434", # set ollama URL arbitrarily - }, - "library": "beautifoulsoup" -} - - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = ScriptCreatorGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/GenerateScraper/benchmark_mistral.py b/examples/benchmarks/GenerateScraper/benchmark_mistral.py deleted file mode 100644 index 87219eb4..00000000 --- a/examples/benchmarks/GenerateScraper/benchmark_mistral.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("GPT4_KEY") - - -graph_config = { - "llm": { - "model": "ollama/mistral", - "temperature": 0, - # "model_tokens": 2000, # set context length arbitrarily, - "base_url": "http://localhost:11434", # set ollama URL arbitrarily - }, - "embeddings": { - "model": "ollama/nomic-embed-text", - "temperature": 0, - "base_url": "http://localhost:11434", # set ollama URL arbitrarily - }, - "library": "beautifoulsoup" -} - - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = ScriptCreatorGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/GenerateScraper/benchmark_openai_gpt35.py b/examples/benchmarks/GenerateScraper/benchmark_openai_gpt35.py deleted file mode 100644 index 83ed3913..00000000 --- a/examples/benchmarks/GenerateScraper/benchmark_openai_gpt35.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "openai/gpt-3.5-turbo", - }, - "library": "beautifoulsoup" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = ScriptCreatorGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/GenerateScraper/benchmark_openai_gpt4.py b/examples/benchmarks/GenerateScraper/benchmark_openai_gpt4.py deleted file mode 100644 index 37791c29..00000000 --- a/examples/benchmarks/GenerateScraper/benchmark_openai_gpt4.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "openai/gpt-4-turbo-2024-04-09", - }, - "library": "beautifoulsoup" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = ScriptCreatorGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/GenerateScraper/inputs/example_1.txt b/examples/benchmarks/GenerateScraper/inputs/example_1.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/benchmarks/GenerateScraper/inputs/example_1.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/benchmarks/GenerateScraper/inputs/example_2.txt b/examples/benchmarks/GenerateScraper/inputs/example_2.txt deleted file mode 100644 index b7810eed..00000000 --- a/examples/benchmarks/GenerateScraper/inputs/example_2.txt +++ /dev/null @@ -1,400 +0,0 @@ -WIRED - The Latest in Technology, Science, Culture and Business | WIRED
Skip to main content

WIRED

Book Excerpt

They Experimented on Themselves in Secret. What They Discovered Helped Win a War

The untold, top-secret story of the British researchers who found the key to keeping humans alive underwater—and helped make D-Day a success.
Business

Microsoft in the age of Satya Nadella

Originally published February 2015: More than five years before Microsoft invested its first $1 billion in OpenAI, its engineers were hard at work on something that they believed would transform consumer computing, and it wasn’t artificial intelligence.
- WIRED - The Latest in Technology, Science, Culture and Business | WIRED -
Skip to main content

WIRED

Book Excerpt

They Experimented on Themselves in Secret. What They Discovered Helped Win a War

The untold, top-secret story of the British researchers who found the key to keeping humans alive underwater—and helped make D-Day a success.
Business

Microsoft in the age of Satya Nadella

Originally published February 2015: More than five years before Microsoft invested its first $1 billion in OpenAI, its engineers were hard at work on something that they believed would transform consumer computing, and it wasn’t artificial intelligence.
-WIRED - The Latest in Technology, Science, Culture and Business | WIRED
Skip to main content

WIRED

Book Excerpt

They Experimented on Themselves in Secret. What They Discovered Helped Win a War

The untold, top-secret story of the British researchers who found the key to keeping humans alive underwater—and helped make D-Day a success.
Business

Microsoft in the age of Satya Nadella

Originally published February 2015: More than five years before Microsoft invested its first $1 billion in OpenAI, its engineers were hard at work on something that they believed would transform consumer computing, and it wasn’t artificial intelligence.
\ No newline at end of file diff --git a/examples/benchmarks/SmartScraper/.env.example b/examples/benchmarks/SmartScraper/.env.example deleted file mode 100644 index 599a2397..00000000 --- a/examples/benchmarks/SmartScraper/.env.example +++ /dev/null @@ -1 +0,0 @@ -OPENAI_APIKEY="your openai key here" \ No newline at end of file diff --git a/examples/benchmarks/SmartScraper/Readme.md b/examples/benchmarks/SmartScraper/Readme.md deleted file mode 100644 index 9c9f9c37..00000000 --- a/examples/benchmarks/SmartScraper/Readme.md +++ /dev/null @@ -1,42 +0,0 @@ -# Local models -# Local models -The two websites benchmark are: -- Example 1: https://perinim.github.io/projects -- Example 2: https://www.wired.com (at 17/4/2024) - -Both are strored locally as txt file in .txt format because in this way we do not have to think about the internet connection - -| Hardware | Model | Example 1 | Example 2 | -| ---------------------- | --------------------------------------- | --------- | --------- | -| Macbook 14' m1 pro | Mistral on Ollama with nomic-embed-text | 16.291s | 38.74s | -| Macbook m2 max | Mistral on Ollama with nomic-embed-text | | | -| Macbook 14' m1 pro
| Llama3 on Ollama with nomic-embed-text | 12.88s | 13.84s | -| Macbook m2 max
| Llama3 on Ollama with nomic-embed-text | | | - -**Note**: the examples on Docker are not runned on other devices than the Macbook because the performance are to slow (10 times slower than Ollama). Indeed the results are the following: - -| Hardware | Example 1 | Example 2 | -| ------------------ | --------- | --------- | -| Macbook 14' m1 pro | 139.89 | Too long | -# Performance on APIs services -### Example 1: personal portfolio -**URL**: https://perinim.github.io/projects -**Task**: List me all the projects with their description. - -| Name | Execution time (seconds) | total_tokens | prompt_tokens | completion_tokens | successful_requests | total_cost_USD | -| ------------------------------- | ------------------------ | ------------ | ------------- | ----------------- | ------------------- | -------------- | -| gpt-3.5-turbo | 4.132s | 438 | 303 | 135 | 1 | 0.000724 | -| gpt-4-turbo-preview | 6.965s | 442 | 303 | 139 | 1 | 0.0072 | -| gpt-4-o | 4.446s | 444 | 305 | 139 | 1 | 0 | -| Grooq with nomic-embed-text
| 1.335s | 648 | 482 | 166 | 1 | 0 | - -### Example 2: Wired -**URL**: https://www.wired.com -**Task**: List me all the articles with their description. - -| Name | Execution time (seconds) | total_tokens | prompt_tokens | completion_tokens | successful_requests | total_cost_USD | -| ------------------------------- | ------------------------ | ------------ | ------------- | ----------------- | ------------------- | -------------- | -| gpt-3.5-turbo | 8.836s | 1167 | 726 | 441 | 1 | 0.001971 | -| gpt-4-turbo-preview | 21.53s | 1205 | 726 | 479 | 1 | 0.02163 | -| gpt-4-o | 15.27s | 1400 | 715 | 685 | 1 | 0 | -| Grooq with nomic-embed-text
| 3.82s | 2459 | 2192 | 267 | 1 | 0 | diff --git a/examples/benchmarks/SmartScraper/benchmark_docker.py b/examples/benchmarks/SmartScraper/benchmark_docker.py deleted file mode 100644 index e5754c4b..00000000 --- a/examples/benchmarks/SmartScraper/benchmark_docker.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ollama/mistral", - "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly - # "model_tokens": 2000, # set context length arbitrarily - }, - "embeddings": { - "model": "ollama/nomic-embed-text", - "temperature": 0, - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = SmartScraperGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/SmartScraper/benchmark_groq.py b/examples/benchmarks/SmartScraper/benchmark_groq.py deleted file mode 100644 index e769ee52..00000000 --- a/examples/benchmarks/SmartScraper/benchmark_groq.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "embeddings": { - "model": "ollama/nomic-embed-text", - "temperature": 0, - "base_url": "http://localhost:11434", # set ollama URL arbitrarily - }, - "headless": False -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = SmartScraperGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/SmartScraper/benchmark_llama3.py b/examples/benchmarks/SmartScraper/benchmark_llama3.py deleted file mode 100644 index 2b182f20..00000000 --- a/examples/benchmarks/SmartScraper/benchmark_llama3.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ollama/llama3", - "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly - # "model_tokens": 2000, # set context length arbitrarily - "base_url": "http://localhost:11434", - }, - "embeddings": { - "model": "ollama/nomic-embed-text", - "temperature": 0, - "base_url": "http://localhost:11434", - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = SmartScraperGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/SmartScraper/benchmark_mistral.py b/examples/benchmarks/SmartScraper/benchmark_mistral.py deleted file mode 100644 index 0e6e53e5..00000000 --- a/examples/benchmarks/SmartScraper/benchmark_mistral.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ollama/mistral", - "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly - # "model_tokens": 2000, # set context length arbitrarily - "base_url": "http://localhost:11434", - }, - "embeddings": { - "model": "ollama/nomic-embed-text", - "temperature": 0, - "base_url": "http://localhost:11434", - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = SmartScraperGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/SmartScraper/benchmark_openai_gpt35.py b/examples/benchmarks/SmartScraper/benchmark_openai_gpt35.py deleted file mode 100644 index 659d2c78..00000000 --- a/examples/benchmarks/SmartScraper/benchmark_openai_gpt35.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "openai/gpt-3.5-turbo", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = SmartScraperGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/SmartScraper/benchmark_openai_gpt4.py b/examples/benchmarks/SmartScraper/benchmark_openai_gpt4.py deleted file mode 100644 index a23901a9..00000000 --- a/examples/benchmarks/SmartScraper/benchmark_openai_gpt4.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "openai/gpt-4-turbo", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = SmartScraperGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/SmartScraper/benchmark_openai_gpt4o.py b/examples/benchmarks/SmartScraper/benchmark_openai_gpt4o.py deleted file mode 100644 index 8b2da6d7..00000000 --- a/examples/benchmarks/SmartScraper/benchmark_openai_gpt4o.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ -files = ["inputs/example_1.txt", "inputs/example_2.txt"] -tasks = ["List me all the projects with their description.", - "List me all the articles with their description."] - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "openai/gpt-4o", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -for i in range(0, 2): - with open(files[i], 'r', encoding="utf-8") as file: - text = file.read() - - smart_scraper_graph = SmartScraperGraph( - prompt=tasks[i], - source=text, - config=graph_config - ) - - result = smart_scraper_graph.run() - print(result) - # ************************************************ - # Get graph execution info - # ************************************************ - - graph_exec_info = smart_scraper_graph.get_execution_info() - print(prettify_exec_info(graph_exec_info)) diff --git a/examples/benchmarks/SmartScraper/inputs/example_1.txt b/examples/benchmarks/SmartScraper/inputs/example_1.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/benchmarks/SmartScraper/inputs/example_1.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/benchmarks/SmartScraper/inputs/example_2.txt b/examples/benchmarks/SmartScraper/inputs/example_2.txt deleted file mode 100644 index b7810eed..00000000 --- a/examples/benchmarks/SmartScraper/inputs/example_2.txt +++ /dev/null @@ -1,400 +0,0 @@ -WIRED - The Latest in Technology, Science, Culture and Business | WIRED
Skip to main content

WIRED

Book Excerpt

They Experimented on Themselves in Secret. What They Discovered Helped Win a War

The untold, top-secret story of the British researchers who found the key to keeping humans alive underwater—and helped make D-Day a success.
Business

Microsoft in the age of Satya Nadella

Originally published February 2015: More than five years before Microsoft invested its first $1 billion in OpenAI, its engineers were hard at work on something that they believed would transform consumer computing, and it wasn’t artificial intelligence.
- WIRED - The Latest in Technology, Science, Culture and Business | WIRED -
Skip to main content

WIRED

Book Excerpt

They Experimented on Themselves in Secret. What They Discovered Helped Win a War

The untold, top-secret story of the British researchers who found the key to keeping humans alive underwater—and helped make D-Day a success.
Business

Microsoft in the age of Satya Nadella

Originally published February 2015: More than five years before Microsoft invested its first $1 billion in OpenAI, its engineers were hard at work on something that they believed would transform consumer computing, and it wasn’t artificial intelligence.
-WIRED - The Latest in Technology, Science, Culture and Business | WIRED
Skip to main content

WIRED

Book Excerpt

They Experimented on Themselves in Secret. What They Discovered Helped Win a War

The untold, top-secret story of the British researchers who found the key to keeping humans alive underwater—and helped make D-Day a success.
Business

Microsoft in the age of Satya Nadella

Originally published February 2015: More than five years before Microsoft invested its first $1 billion in OpenAI, its engineers were hard at work on something that they believed would transform consumer computing, and it wasn’t artificial intelligence.
\ No newline at end of file diff --git a/examples/benchmarks/readme.md b/examples/benchmarks/readme.md deleted file mode 100644 index ca672ad0..00000000 --- a/examples/benchmarks/readme.md +++ /dev/null @@ -1,4 +0,0 @@ -These 2 subfolders contain all the scripts and performance documents for the 2 graphs used for the scrapers. -In particular: -* __GenerateScraper__: contains the benchmarks for GenerateScraper class -* __SmartScraper__: contains the benchamrks for SmartScraper class \ No newline at end of file diff --git a/examples/code_generator_graph/.env.example b/examples/code_generator_graph/.env.example new file mode 100644 index 00000000..a93912e4 --- /dev/null +++ b/examples/code_generator_graph/.env.example @@ -0,0 +1,14 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# Code Generator Settings +DEFAULT_LANGUAGE=python +GENERATE_TESTS=true +ADD_DOCUMENTATION=true +CODE_STYLE=pep8 +TYPE_CHECKING=true \ No newline at end of file diff --git a/examples/code_generator_graph/README.md b/examples/code_generator_graph/README.md new file mode 100644 index 00000000..bc4b5dec --- /dev/null +++ b/examples/code_generator_graph/README.md @@ -0,0 +1,30 @@ +# Code Generator Graph Example + +This example demonstrates how to use Scrapegraph-ai to generate code based on specifications and requirements. + +## Features + +- Code generation from specifications +- Multiple programming languages support +- Code documentation +- Best practices implementation + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import CodeGeneratorGraph + +graph = CodeGeneratorGraph() +code = graph.generate("code specification") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/local_models/code_generator_graph_ollama.py b/examples/code_generator_graph/ollama/code_generator_graph_ollama.py similarity index 100% rename from examples/local_models/code_generator_graph_ollama.py rename to examples/code_generator_graph/ollama/code_generator_graph_ollama.py diff --git a/examples/openai/code_generator_graph_openai.py b/examples/code_generator_graph/openai/code_generator_graph_openai.py similarity index 100% rename from examples/openai/code_generator_graph_openai.py rename to examples/code_generator_graph/openai/code_generator_graph_openai.py diff --git a/examples/csv_scraper_graph/.env.example b/examples/csv_scraper_graph/.env.example new file mode 100644 index 00000000..1917f9aa --- /dev/null +++ b/examples/csv_scraper_graph/.env.example @@ -0,0 +1,11 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# CSV Scraper Settings +CSV_DELIMITER=, +MAX_ROWS=1000 \ No newline at end of file diff --git a/examples/csv_scraper_graph/README.md b/examples/csv_scraper_graph/README.md new file mode 100644 index 00000000..d39858b0 --- /dev/null +++ b/examples/csv_scraper_graph/README.md @@ -0,0 +1,30 @@ +# CSV Scraper Graph Example + +This example demonstrates how to use Scrapegraph-ai to extract data from web sources and save it in CSV format. + +## Features + +- Table data extraction +- CSV formatting +- Data cleaning +- Structured output + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import CsvScraperGraph + +graph = CsvScraperGraph() +csv_data = graph.scrape("https://example.com/table") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/local_models/csv_scraper_graph_multi_ollama.py b/examples/csv_scraper_graph/ollama/csv_scraper_graph_multi_ollama.py similarity index 86% rename from examples/local_models/csv_scraper_graph_multi_ollama.py rename to examples/csv_scraper_graph/ollama/csv_scraper_graph_multi_ollama.py index fb6bce51..558a876f 100644 --- a/examples/local_models/csv_scraper_graph_multi_ollama.py +++ b/examples/csv_scraper_graph/ollama/csv_scraper_graph_multi_ollama.py @@ -3,9 +3,9 @@ """ import os -import pandas as pd + from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info +from scrapegraphai.utils import prettify_exec_info # ************************************************ # Read the CSV file @@ -15,7 +15,8 @@ curr_dir = os.path.dirname(os.path.realpath(__file__)) file_path = os.path.join(curr_dir, FILE_NAME) -text = pd.read_csv(file_path) +with open(file_path, "r") as file: + text = file.read() # ************************************************ # Define the configuration for the graph @@ -44,7 +45,7 @@ csv_scraper_graph = CSVScraperMultiGraph( prompt="List me all the last names", source=[str(text), str(text)], - config=graph_config + config=graph_config, ) result = csv_scraper_graph.run() @@ -56,7 +57,3 @@ graph_exec_info = csv_scraper_graph.get_execution_info() print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/local_models/csv_scraper_ollama.py b/examples/csv_scraper_graph/ollama/csv_scraper_ollama.py similarity index 86% rename from examples/local_models/csv_scraper_ollama.py rename to examples/csv_scraper_graph/ollama/csv_scraper_ollama.py index 8d1edbd7..d6e6eab2 100644 --- a/examples/local_models/csv_scraper_ollama.py +++ b/examples/csv_scraper_graph/ollama/csv_scraper_ollama.py @@ -3,9 +3,9 @@ """ import os -import pandas as pd + from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info +from scrapegraphai.utils import prettify_exec_info # ************************************************ # Read the CSV file @@ -15,7 +15,8 @@ curr_dir = os.path.dirname(os.path.realpath(__file__)) file_path = os.path.join(curr_dir, FILE_NAME) -text = pd.read_csv(file_path) +with open(file_path, "r") as file: + text = file.read() # ************************************************ # Define the configuration for the graph @@ -44,7 +45,7 @@ csv_scraper_graph = CSVScraperGraph( prompt="List me all the last names", source=str(text), # Pass the content of the file, not the file object - config=graph_config + config=graph_config, ) result = csv_scraper_graph.run() @@ -56,7 +57,3 @@ graph_exec_info = csv_scraper_graph.get_execution_info() print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/anthropic/inputs/username.csv b/examples/csv_scraper_graph/ollama/inputs/username.csv similarity index 100% rename from examples/anthropic/inputs/username.csv rename to examples/csv_scraper_graph/ollama/inputs/username.csv diff --git a/examples/openai/csv_scraper_graph_multi_openai.py b/examples/csv_scraper_graph/openai/csv_scraper_graph_multi_openai.py similarity index 83% rename from examples/openai/csv_scraper_graph_multi_openai.py rename to examples/csv_scraper_graph/openai/csv_scraper_graph_multi_openai.py index 6ed33c90..b7bc83ae 100644 --- a/examples/openai/csv_scraper_graph_multi_openai.py +++ b/examples/csv_scraper_graph/openai/csv_scraper_graph_multi_openai.py @@ -1,11 +1,13 @@ """ Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents """ + import os + from dotenv import load_dotenv -import pandas as pd + from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info +from scrapegraphai.utils import prettify_exec_info load_dotenv() # ************************************************ @@ -16,7 +18,8 @@ curr_dir = os.path.dirname(os.path.realpath(__file__)) file_path = os.path.join(curr_dir, FILE_NAME) -text = pd.read_csv(file_path) +with open(file_path, "r") as file: + text = file.read() # ************************************************ # Define the configuration for the graph @@ -24,7 +27,7 @@ openai_key = os.getenv("OPENAI_APIKEY") graph_config = { - "llm": { + "llm": { "api_key": openai_key, "model": "openai/gpt-4o", }, @@ -37,7 +40,7 @@ csv_scraper_graph = CSVScraperMultiGraph( prompt="List me all the last names", source=[str(text), str(text)], - config=graph_config + config=graph_config, ) result = csv_scraper_graph.run() @@ -49,7 +52,3 @@ graph_exec_info = csv_scraper_graph.get_execution_info() print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/openai/csv_scraper_openai.py b/examples/csv_scraper_graph/openai/csv_scraper_openai.py similarity index 84% rename from examples/openai/csv_scraper_openai.py rename to examples/csv_scraper_graph/openai/csv_scraper_openai.py index d9527b86..a0abd714 100644 --- a/examples/openai/csv_scraper_openai.py +++ b/examples/csv_scraper_graph/openai/csv_scraper_openai.py @@ -1,11 +1,13 @@ """ Basic example of scraping pipeline using CSVScraperGraph from CSV documents """ + import os + from dotenv import load_dotenv -import pandas as pd + from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info +from scrapegraphai.utils import prettify_exec_info load_dotenv() @@ -17,7 +19,8 @@ curr_dir = os.path.dirname(os.path.realpath(__file__)) file_path = os.path.join(curr_dir, FILE_NAME) -text = pd.read_csv(file_path) +with open(file_path, "r") as file: + text = file.read() # ************************************************ # Define the configuration for the graph @@ -39,7 +42,7 @@ csv_scraper_graph = CSVScraperGraph( prompt="List me all the last names", source=str(text), # Pass the content of the file, not the file object - config=graph_config + config=graph_config, ) result = csv_scraper_graph.run() @@ -51,7 +54,3 @@ graph_exec_info = csv_scraper_graph.get_execution_info() print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/azure/inputs/username.csv b/examples/csv_scraper_graph/openai/inputs/username.csv similarity index 100% rename from examples/azure/inputs/username.csv rename to examples/csv_scraper_graph/openai/inputs/username.csv diff --git a/examples/custom_graph/.env.example b/examples/custom_graph/.env.example new file mode 100644 index 00000000..9eac4cb8 --- /dev/null +++ b/examples/custom_graph/.env.example @@ -0,0 +1,13 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# Custom Graph Settings +CUSTOM_NODE_TIMEOUT=30 +MAX_NODES=10 +DEBUG_MODE=false +LOG_LEVEL=info \ No newline at end of file diff --git a/examples/custom_graph/README.md b/examples/custom_graph/README.md new file mode 100644 index 00000000..e6d3b88a --- /dev/null +++ b/examples/custom_graph/README.md @@ -0,0 +1,31 @@ +# Custom Graph Example + +This example demonstrates how to create and implement custom graphs using Scrapegraph-ai. + +## Features + +- Custom node creation +- Graph customization +- Pipeline configuration +- Custom data processing + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import CustomGraph + +graph = CustomGraph() +graph.add_node("custom_node", CustomNode()) +results = graph.process() +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/local_models/custom_graph_ollama.py b/examples/custom_graph/ollama/custom_graph_ollama.py similarity index 100% rename from examples/local_models/custom_graph_ollama.py rename to examples/custom_graph/ollama/custom_graph_ollama.py diff --git a/examples/openai/custom_graph_openai.py b/examples/custom_graph/openai/custom_graph_openai.py similarity index 100% rename from examples/openai/custom_graph_openai.py rename to examples/custom_graph/openai/custom_graph_openai.py diff --git a/examples/deepseek/.env.example b/examples/deepseek/.env.example deleted file mode 100644 index 37511138..00000000 --- a/examples/deepseek/.env.example +++ /dev/null @@ -1 +0,0 @@ -DEEPSEEK_APIKEY="your api key" \ No newline at end of file diff --git a/examples/deepseek/code_generator_graph_deepseek.py b/examples/deepseek/code_generator_graph_deepseek.py deleted file mode 100644 index f78a42b6..00000000 --- a/examples/deepseek/code_generator_graph_deepseek.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) diff --git a/examples/deepseek/csv_scraper_deepseek.py b/examples/deepseek/csv_scraper_deepseek.py deleted file mode 100644 index 6ef0ac92..00000000 --- a/examples/deepseek/csv_scraper_deepseek.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/deepseek/csv_scraper_graph_multi_deepseek.py b/examples/deepseek/csv_scraper_graph_multi_deepseek.py deleted file mode 100644 index 95474360..00000000 --- a/examples/deepseek/csv_scraper_graph_multi_deepseek.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/deepseek/depth_search_graph_deepseek.py b/examples/deepseek/depth_search_graph_deepseek.py deleted file mode 100644 index 064690a5..00000000 --- a/examples/deepseek/depth_search_graph_deepseek.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/deepseek/document_scraper_deepseek.py b/examples/deepseek/document_scraper_deepseek.py deleted file mode 100644 index e94826d3..00000000 --- a/examples/deepseek/document_scraper_deepseek.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/deepseek/inputs/books.xml b/examples/deepseek/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/deepseek/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/deepseek/inputs/example.json b/examples/deepseek/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/deepseek/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/deepseek/inputs/username.csv b/examples/deepseek/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/deepseek/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/deepseek/json_scraper_deepseek.py b/examples/deepseek/json_scraper_deepseek.py deleted file mode 100644 index d714c1db..00000000 --- a/examples/deepseek/json_scraper_deepseek.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/deepseek/json_scraper_multi_deepseek.py b/examples/deepseek/json_scraper_multi_deepseek.py deleted file mode 100644 index 893937cd..00000000 --- a/examples/deepseek/json_scraper_multi_deepseek.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -Module for showing how JSONScraperMultiGraph multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/deepseek/rate_limit_deepseek.py b/examples/deepseek/rate_limit_deepseek.py deleted file mode 100644 index 16781f39..00000000 --- a/examples/deepseek/rate_limit_deepseek.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - "rate_limit": { - "requests_per_second": 1 - } - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/deepseek/scrape_plain_text_deepseek.py b/examples/deepseek/scrape_plain_text_deepseek.py deleted file mode 100644 index 2b243d35..00000000 --- a/examples/deepseek/scrape_plain_text_deepseek.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/deepseek/script_generator_deepseek.py b/examples/deepseek/script_generator_deepseek.py deleted file mode 100644 index 899c7a35..00000000 --- a/examples/deepseek/script_generator_deepseek.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/deepseek/script_multi_generator_deepseek.py b/examples/deepseek/script_multi_generator_deepseek.py deleted file mode 100644 index 48ca2d20..00000000 --- a/examples/deepseek/script_multi_generator_deepseek.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/deepseek/search_graph_deepseek.py b/examples/deepseek/search_graph_deepseek.py deleted file mode 100644 index 7a3baf0d..00000000 --- a/examples/deepseek/search_graph_deepseek.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "max_results": 2, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/deepseek/search_graph_schema_deepseek.py b/examples/deepseek/search_graph_schema_deepseek.py deleted file mode 100644 index f5f20e25..00000000 --- a/examples/deepseek/search_graph_schema_deepseek.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Example of Search Graph -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/deepseek/search_link_graph_deepseek.py b/examples/deepseek/search_link_graph_deepseek.py deleted file mode 100644 index dac13737..00000000 --- a/examples/deepseek/search_link_graph_deepseek.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/deepseek/smart_scraper_deepseek.py b/examples/deepseek/smart_scraper_deepseek.py deleted file mode 100644 index 0eac94e8..00000000 --- a/examples/deepseek/smart_scraper_deepseek.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/deepseek/smart_scraper_lite_deepseek.py b/examples/deepseek/smart_scraper_lite_deepseek.py deleted file mode 100644 index a70d76b0..00000000 --- a/examples/deepseek/smart_scraper_lite_deepseek.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("DEEPSEEK_API_KEY"), - "model": "deepseek/deepseek-coder-33b-instruct", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/deepseek/smart_scraper_multi_concat_deepseek.py b/examples/deepseek/smart_scraper_multi_concat_deepseek.py deleted file mode 100644 index eeb1816c..00000000 --- a/examples/deepseek/smart_scraper_multi_concat_deepseek.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/deepseek/smart_scraper_multi_deepseek.py b/examples/deepseek/smart_scraper_multi_deepseek.py deleted file mode 100644 index 5923e302..00000000 --- a/examples/deepseek/smart_scraper_multi_deepseek.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/deepseek/smart_scraper_multi_lite_deepseek.py b/examples/deepseek/smart_scraper_multi_lite_deepseek.py deleted file mode 100644 index eb5eea01..00000000 --- a/examples/deepseek/smart_scraper_multi_lite_deepseek.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("DEEPSEEK_API_KEY"), - "model": "deepseek/deepseek-coder-33b-instruct", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/deepseek/smart_scraper_schema_deepseek.py b/examples/deepseek/smart_scraper_schema_deepseek.py deleted file mode 100644 index fd87fbdc..00000000 --- a/examples/deepseek/smart_scraper_schema_deepseek.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from typing import List -from pydantic import BaseModel, Field -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/deepseek/xml_scraper_deepseek.py b/examples/deepseek/xml_scraper_deepseek.py deleted file mode 100644 index d66b0eab..00000000 --- a/examples/deepseek/xml_scraper_deepseek.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/deepseek/xml_scraper_graph_multi_deepseek.py b/examples/deepseek/xml_scraper_graph_multi_deepseek.py deleted file mode 100644 index 2d190926..00000000 --- a/examples/deepseek/xml_scraper_graph_multi_deepseek.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -deepseek_key = os.getenv("DEEPSEEK_APIKEY") - -graph_config = { - "llm": { - "model": "deepseek/deepseek-chat", - "api_key": deepseek_key, - }, - "verbose": True, -} -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/depth_search_graph/.env.example b/examples/depth_search_graph/.env.example new file mode 100644 index 00000000..8c10cfbb --- /dev/null +++ b/examples/depth_search_graph/.env.example @@ -0,0 +1,14 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# Depth Search Settings +MAX_DEPTH=5 +CRAWL_DELAY=1 +RESPECT_ROBOTS_TXT=true +MAX_PAGES_PER_DOMAIN=100 +USER_AGENT=Mozilla/5.0 \ No newline at end of file diff --git a/examples/depth_search_graph/README.md b/examples/depth_search_graph/README.md new file mode 100644 index 00000000..c4ce05df --- /dev/null +++ b/examples/depth_search_graph/README.md @@ -0,0 +1,30 @@ +# Depth Search Graph Example + +This example demonstrates how to use Scrapegraph-ai for deep web crawling and content exploration. + +## Features + +- Deep web crawling +- Content discovery +- Link analysis +- Recursive search + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import DepthSearchGraph + +graph = DepthSearchGraph() +results = graph.search("https://example.com", depth=3) +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/local_models/depth_search_graph_ollama.py b/examples/depth_search_graph/ollama/depth_search_graph_ollama.py similarity index 100% rename from examples/local_models/depth_search_graph_ollama.py rename to examples/depth_search_graph/ollama/depth_search_graph_ollama.py diff --git a/examples/openai/depth_search_graph_openai.py b/examples/depth_search_graph/openai/depth_search_graph_openai.py similarity index 100% rename from examples/openai/depth_search_graph_openai.py rename to examples/depth_search_graph/openai/depth_search_graph_openai.py diff --git a/examples/document_scraper_graph/.env.example b/examples/document_scraper_graph/.env.example new file mode 100644 index 00000000..2e7bab46 --- /dev/null +++ b/examples/document_scraper_graph/.env.example @@ -0,0 +1,13 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# Document Scraper Settings +OCR_ENABLED=true +EXTRACT_METADATA=true +MAX_FILE_SIZE=10485760 # 10MB +SUPPORTED_FORMATS=pdf,doc,docx,txt \ No newline at end of file diff --git a/examples/document_scraper_graph/README.md b/examples/document_scraper_graph/README.md new file mode 100644 index 00000000..f8561ee7 --- /dev/null +++ b/examples/document_scraper_graph/README.md @@ -0,0 +1,30 @@ +# Document Scraper Graph Example + +This example demonstrates how to use Scrapegraph-ai to extract data from various document formats (PDF, DOC, DOCX, etc.). + +## Features + +- Multi-format document support +- Text extraction +- Document parsing +- Metadata extraction + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import DocumentScraperGraph + +graph = DocumentScraperGraph() +content = graph.scrape("document.pdf") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/local_models/document_scraper_ollama.py b/examples/document_scraper_graph/ollama/document_scraper_ollama.py similarity index 100% rename from examples/local_models/document_scraper_ollama.py rename to examples/document_scraper_graph/ollama/document_scraper_ollama.py diff --git a/examples/anthropic/inputs/plain_html_example.txt b/examples/document_scraper_graph/ollama/inputs/plain_html_example.txt similarity index 100% rename from examples/anthropic/inputs/plain_html_example.txt rename to examples/document_scraper_graph/ollama/inputs/plain_html_example.txt diff --git a/examples/openai/document_scraper_openai.py b/examples/document_scraper_graph/openai/document_scraper_openai.py similarity index 100% rename from examples/openai/document_scraper_openai.py rename to examples/document_scraper_graph/openai/document_scraper_openai.py diff --git a/examples/mistral/inputs/markdown_example.md b/examples/document_scraper_graph/openai/inputs/markdown_example.md similarity index 100% rename from examples/mistral/inputs/markdown_example.md rename to examples/document_scraper_graph/openai/inputs/markdown_example.md diff --git a/examples/bedrock/inputs/plain_html_example.txt b/examples/document_scraper_graph/openai/inputs/plain_html_example.txt similarity index 100% rename from examples/bedrock/inputs/plain_html_example.txt rename to examples/document_scraper_graph/openai/inputs/plain_html_example.txt diff --git a/examples/ernie/code_generator_graph_ernie.py b/examples/ernie/code_generator_graph_ernie.py deleted file mode 100644 index 65b8e4b9..00000000 --- a/examples/ernie/code_generator_graph_ernie.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) \ No newline at end of file diff --git a/examples/ernie/csv_scraper_ernie.py b/examples/ernie/csv_scraper_ernie.py deleted file mode 100644 index 6f4335b6..00000000 --- a/examples/ernie/csv_scraper_ernie.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - } -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/ernie/custom_graph_ernie.py b/examples/ernie/custom_graph_ernie.py deleted file mode 100644 index a987560e..00000000 --- a/examples/ernie/custom_graph_ernie.py +++ /dev/null @@ -1,106 +0,0 @@ -""" -Example of custom graph using existing nodes -""" -from langchain_openai import OpenAIEmbeddings -from langchain_openai import ChatOpenAI -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import FetchNode, ParseNode, RAGNode, GenerateAnswerNode, RobotsNode - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - } -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = ChatOpenAI(graph_config["llm"]) -embedder = OpenAIEmbeddings(api_key=llm_model.openai_api_key) - -# define the nodes for the graph -robot_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={ - "llm_model": llm_model, - "force_scraping": True, - "verbose": True, - } -) - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "verbose": True, - "headless": True, - } -) -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={ - "chunk_size": 4096, - "verbose": True, - } -) -rag_node = RAGNode( - input="user_prompt & (parsed_doc | doc)", - output=["relevant_chunks"], - node_config={ - "llm_model": llm_model, - "embedder_model": embedder, - "verbose": True, - } -) -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={ - "llm_model": llm_model, - "verbose": True, - } -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes=[ - robot_node, - fetch_node, - parse_node, - rag_node, - generate_answer_node, - ], - edges=[ - (robot_node, fetch_node), - (fetch_node, parse_node), - (parse_node, rag_node), - (rag_node, generate_answer_node) - ], - entry_point=robot_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "Describe the content", - "url": "https://example.com/" -}) - -# get the answer from the result -result = result.get("answer", "No answer found.") -print(result) diff --git a/examples/ernie/depth_search_graph_ernie.py b/examples/ernie/depth_search_graph_ernie.py deleted file mode 100644 index 99470d8d..00000000 --- a/examples/ernie/depth_search_graph_ernie.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -depth_search_graph_opeani example -""" -from scrapegraphai.graphs import DepthSearchGraph - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/ernie/document_scraper_anthropic_ernie.py b/examples/ernie/document_scraper_anthropic_ernie.py deleted file mode 100644 index 74d91be1..00000000 --- a/examples/ernie/document_scraper_anthropic_ernie.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from scrapegraphai.graphs import DocumentScraperGraph - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - } -} - - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/ernie/inputs/books.xml b/examples/ernie/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/ernie/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/ernie/inputs/example.json b/examples/ernie/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/ernie/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/ernie/inputs/plain_html_example.txt b/examples/ernie/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/ernie/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/ernie/inputs/username.csv b/examples/ernie/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/ernie/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/ernie/json_scraper_ernie.py b/examples/ernie/json_scraper_ernie.py deleted file mode 100644 index 35324da2..00000000 --- a/examples/ernie/json_scraper_ernie.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - } -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/ernie/rate_limit_ernie.py b/examples/ernie/rate_limit_ernie.py deleted file mode 100644 index 043029a7..00000000 --- a/examples/ernie/rate_limit_ernie.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1, - "rate_limit": { - "requests_per_second": 1 - }, - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config, -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/ernie/scrape_plain_text_ernie.py b/examples/ernie/scrape_plain_text_ernie.py deleted file mode 100644 index dde49537..00000000 --- a/examples/ernie/scrape_plain_text_ernie.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/ernie/script_generator_ernie.py b/examples/ernie/script_generator_ernie.py deleted file mode 100644 index f518739c..00000000 --- a/examples/ernie/script_generator_ernie.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/ernie/script_multi_generator_ernie.py b/examples/ernie/script_multi_generator_ernie.py deleted file mode 100644 index 4b3c88f7..00000000 --- a/examples/ernie/script_multi_generator_ernie.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/ernie/search_graph_ernie.py b/examples/ernie/search_graph_ernie.py deleted file mode 100644 index ff9b3d8b..00000000 --- a/examples/ernie/search_graph_ernie.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Example of Search Graph -""" -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/ernie/search_link_graph_ernie.py b/examples/ernie/search_link_graph_ernie.py deleted file mode 100644 index 645dd505..00000000 --- a/examples/ernie/search_link_graph_ernie.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Example of Search Graph -""" -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/ernie/smart_scraper_ernie.py b/examples/ernie/smart_scraper_ernie.py deleted file mode 100644 index 4bbe608a..00000000 --- a/examples/ernie/smart_scraper_ernie.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config, -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/ernie/smart_scraper_lite_ernie.py b/examples/ernie/smart_scraper_lite_ernie.py deleted file mode 100644 index 5d3ba9d9..00000000 --- a/examples/ernie/smart_scraper_lite_ernie.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ERNIE_API_KEY"), - "model": "ernie/ernie-bot-4", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/ernie/smart_scraper_multi_concat_ernie.py b/examples/ernie/smart_scraper_multi_concat_ernie.py deleted file mode 100644 index 5be9898d..00000000 --- a/examples/ernie/smart_scraper_multi_concat_ernie.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import json -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "library": "beautifulsoup" -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/ernie/smart_scraper_multi_ernie.py b/examples/ernie/smart_scraper_multi_ernie.py deleted file mode 100644 index 4e44ab6a..00000000 --- a/examples/ernie/smart_scraper_multi_ernie.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "verbose": True, - "headless": False, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/ernie/smart_scraper_multi_lite_ernie.py b/examples/ernie/smart_scraper_multi_lite_ernie.py deleted file mode 100644 index 777a760e..00000000 --- a/examples/ernie/smart_scraper_multi_lite_ernie.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ERNIE_API_KEY"), - "model": "ernie/ernie-bot-4", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/ernie/smart_scraper_schema_ernie.py b/examples/ernie/smart_scraper_schema_ernie.py deleted file mode 100644 index e9d9ab0a..00000000 --- a/examples/ernie/smart_scraper_schema_ernie.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" -import json -import os -from typing import Dict -from dotenv import load_dotenv -from pydantic import BaseModel -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ -class Project(BaseModel): - title: str - description: str - - -class Projects(BaseModel): - Projects: Dict[str, Project] - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config, -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/ernie/speech_graph_ernie.py b/examples/ernie/speech_graph_ernie.py deleted file mode 100644 index 0b4ed620..00000000 --- a/examples/ernie/speech_graph_ernie.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using SpeechSummaryGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SpeechGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define audio output path -# ************************************************ - -FILE_NAME = "website_summary.mp3" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -output_path = os.path.join(curr_dir, FILE_NAME) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "tts_model": { - "api_key": openai_key, - "model": "tts-1", - "voice": "alloy" - }, - "output_path": output_path, -} - -# ************************************************ -# Create the SpeechGraph instance and run it -# ************************************************ - -speech_graph = SpeechGraph( - prompt="Make a detailed audio summary of the projects.", - source="https://perinim.github.io/projects/", - config=graph_config, -) - -result = speech_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = speech_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/ernie/xml_scraper_ernie.py b/examples/ernie/xml_scraper_ernie.py deleted file mode 100644 index 90a1230a..00000000 --- a/examples/ernie/xml_scraper_ernie.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "model": "ernie/ernie-bot-turbo", - "ernie_client_id": "", - "ernie_client_secret": "", - "temperature": 0.1 - }, - "verbose":False, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") - diff --git a/examples/fireworks/.env.example b/examples/fireworks/.env.example deleted file mode 100644 index ab200215..00000000 --- a/examples/fireworks/.env.example +++ /dev/null @@ -1 +0,0 @@ -FIREWORKS_APIKEY="your fireworks api key" diff --git a/examples/fireworks/code_generator_graph_fireworks.py b/examples/fireworks/code_generator_graph_fireworks.py deleted file mode 100644 index e38c48a1..00000000 --- a/examples/fireworks/code_generator_graph_fireworks.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -import json -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) \ No newline at end of file diff --git a/examples/fireworks/csv_scraper_fireworks.py b/examples/fireworks/csv_scraper_fireworks.py deleted file mode 100644 index c380f9bd..00000000 --- a/examples/fireworks/csv_scraper_fireworks.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "headless": False, -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/fireworks/csv_scraper_graph_multi_fireworks.py b/examples/fireworks/csv_scraper_graph_multi_fireworks.py deleted file mode 100644 index 61518822..00000000 --- a/examples/fireworks/csv_scraper_graph_multi_fireworks.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/fireworks/custom_graph_fireworks.py b/examples/fireworks/custom_graph_fireworks.py deleted file mode 100644 index 518e9df3..00000000 --- a/examples/fireworks/custom_graph_fireworks.py +++ /dev/null @@ -1,98 +0,0 @@ -""" -Example of custom graph using existing nodes -""" -import os -from dotenv import load_dotenv -from langchain_openai import ChatOpenAI -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import FetchNode, ParseNode, GenerateAnswerNode, RobotsNode -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = ChatOpenAI(graph_config["llm"]) - -# define the nodes for the graph -robot_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={ - "llm_model": llm_model, - "force_scraping": True, - "verbose": True, - } -) - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "verbose": True, - "headless": True, - } -) -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={ - "chunk_size": 4096, - "verbose": True, - } -) - -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={ - "llm_model": llm_model, - "verbose": True, - } -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes=[ - robot_node, - fetch_node, - parse_node, - ], - edges=[ - (robot_node, fetch_node), - (fetch_node, parse_node), - (parse_node, generate_answer_node) - ], - entry_point=robot_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "Describe the content", - "url": "https://example.com/" -}) - -# get the answer from the result -result = result.get("answer", "No answer found.") -print(result) diff --git a/examples/fireworks/depth_search_graph_fireworks.py b/examples/fireworks/depth_search_graph_fireworks.py deleted file mode 100644 index f467be9f..00000000 --- a/examples/fireworks/depth_search_graph_fireworks.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/fireworks/document_scraper_anthropic_fireworks.py b/examples/fireworks/document_scraper_anthropic_fireworks.py deleted file mode 100644 index 33f6c0d5..00000000 --- a/examples/fireworks/document_scraper_anthropic_fireworks.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/fireworks/inputs/books.xml b/examples/fireworks/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/fireworks/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/fireworks/inputs/example.json b/examples/fireworks/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/fireworks/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/fireworks/inputs/plain_html_example.txt b/examples/fireworks/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/fireworks/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/fireworks/inputs/username.csv b/examples/fireworks/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/fireworks/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/fireworks/json_scraper_fireworkspy.py b/examples/fireworks/json_scraper_fireworkspy.py deleted file mode 100644 index ef1b8264..00000000 --- a/examples/fireworks/json_scraper_fireworkspy.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/fireworks/json_scraper_multi_fireworks.py b/examples/fireworks/json_scraper_multi_fireworks.py deleted file mode 100644 index cd16c525..00000000 --- a/examples/fireworks/json_scraper_multi_fireworks.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Module for showing how PDFScraper multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/fireworks/rate_limit_fireworks.py b/examples/fireworks/rate_limit_fireworks.py deleted file mode 100644 index 813b6d5d..00000000 --- a/examples/fireworks/rate_limit_fireworks.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct", - "rate_limit": { - "requests_per_second": 1 - }, - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config, -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/fireworks/scrape_plain_text_fireworks.py b/examples/fireworks/scrape_plain_text_fireworks.py deleted file mode 100644 index c82bdf15..00000000 --- a/examples/fireworks/scrape_plain_text_fireworks.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/fireworks/script_generator_fireworks.py b/examples/fireworks/script_generator_fireworks.py deleted file mode 100644 index d195cbdc..00000000 --- a/examples/fireworks/script_generator_fireworks.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, - "library": "beautifulsoup" - -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/fireworks/script_generator_schema_fireworks.py b/examples/fireworks/script_generator_schema_fireworks.py deleted file mode 100644 index 20e46fb7..00000000 --- a/examples/fireworks/script_generator_schema_fireworks.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "library": "beautifulsoup", -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config, - schema=Projects -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/fireworks/script_multi_generator_fireworks.py b/examples/fireworks/script_multi_generator_fireworks.py deleted file mode 100644 index c0f474dc..00000000 --- a/examples/fireworks/script_multi_generator_fireworks.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "library": "beautifulsoup", -} -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/fireworks/search_graph_fireworks.py b/examples/fireworks/search_graph_fireworks.py deleted file mode 100644 index 72728a28..00000000 --- a/examples/fireworks/search_graph_fireworks.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "max_results": 2, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/fireworks/search_graph_schema_fireworks.py b/examples/fireworks/search_graph_schema_fireworks.py deleted file mode 100644 index bd54a69a..00000000 --- a/examples/fireworks/search_graph_schema_fireworks.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Example of Search Graph -""" - -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "max_results": 2, - "verbose": True, - "headless": False, -} -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/fireworks/search_link_graph_fireworks.py b/examples/fireworks/search_link_graph_fireworks.py deleted file mode 100644 index e71e2a4f..00000000 --- a/examples/fireworks/search_link_graph_fireworks.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "max_results": 2, - "verbose": True, - "headless": False, -} -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/fireworks/smart_scraper_fireworks.py b/examples/fireworks/smart_scraper_fireworks.py deleted file mode 100644 index 2ccac269..00000000 --- a/examples/fireworks/smart_scraper_fireworks.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config, -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/fireworks/smart_scraper_lite_fireworks.py b/examples/fireworks/smart_scraper_lite_fireworks.py deleted file mode 100644 index 6c9a7745..00000000 --- a/examples/fireworks/smart_scraper_lite_fireworks.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("FIREWORKS_API_KEY"), - "model": "fireworks/llama-v2-70b-chat", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/fireworks/smart_scraper_multi_concat_fireworks.py b/examples/fireworks/smart_scraper_multi_concat_fireworks.py deleted file mode 100644 index c0da49a3..00000000 --- a/examples/fireworks/smart_scraper_multi_concat_fireworks.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/fireworks/smart_scraper_multi_fireworks.py b/examples/fireworks/smart_scraper_multi_fireworks.py deleted file mode 100644 index a75f9ab1..00000000 --- a/examples/fireworks/smart_scraper_multi_fireworks.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/fireworks/smart_scraper_multi_lite_fireworks.py b/examples/fireworks/smart_scraper_multi_lite_fireworks.py deleted file mode 100644 index 4ffaf6bb..00000000 --- a/examples/fireworks/smart_scraper_multi_lite_fireworks.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("FIREWORKS_API_KEY"), - "model": "fireworks/llama-v2-70b-chat", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/fireworks/smart_scraper_schema_fireworks.py b/examples/fireworks/smart_scraper_schema_fireworks.py deleted file mode 100644 index b576bc7d..00000000 --- a/examples/fireworks/smart_scraper_schema_fireworks.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) diff --git a/examples/fireworks/xml_scraper_fireworks.py b/examples/fireworks/xml_scraper_fireworks.py deleted file mode 100644 index 88673cf6..00000000 --- a/examples/fireworks/xml_scraper_fireworks.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/fireworks/xml_scraper_graph_multi_fireworks.py b/examples/fireworks/xml_scraper_graph_multi_fireworks.py deleted file mode 100644 index 1744325b..00000000 --- a/examples/fireworks/xml_scraper_graph_multi_fireworks.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -fireworks_api_key = os.getenv("FIREWORKS_APIKEY") - -graph_config = { - "llm": { - "api_key": fireworks_api_key, - "model": "fireworks/accounts/fireworks/models/mixtral-8x7b-instruct" - }, - "verbose": True, - "headless": False, -} -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_genai/.env.example b/examples/google_genai/.env.example deleted file mode 100644 index fc0dacb0..00000000 --- a/examples/google_genai/.env.example +++ /dev/null @@ -1 +0,0 @@ -GOOGLE_APIKEY="your google api key" diff --git a/examples/google_genai/code_generator_graph_gemini.py b/examples/google_genai/code_generator_graph_gemini.py deleted file mode 100644 index 48ea9833..00000000 --- a/examples/google_genai/code_generator_graph_gemini.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) diff --git a/examples/google_genai/csv_scraper_gemini.py b/examples/google_genai/csv_scraper_gemini.py deleted file mode 100644 index cb792169..00000000 --- a/examples/google_genai/csv_scraper_gemini.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the csv file -# ************************************************ - -text = pd.read_csv("inputs/username.csv") - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_genai/csv_scraper_graph_multi_gemini.py b/examples/google_genai/csv_scraper_graph_multi_gemini.py deleted file mode 100644 index a7b252ee..00000000 --- a/examples/google_genai/csv_scraper_graph_multi_gemini.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_genai/depth_search_graph_gemini.py b/examples/google_genai/depth_search_graph_gemini.py deleted file mode 100644 index 956341f4..00000000 --- a/examples/google_genai/depth_search_graph_gemini.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/google_genai/document_scraper_gemini.py b/examples/google_genai/document_scraper_gemini.py deleted file mode 100644 index efb22d68..00000000 --- a/examples/google_genai/document_scraper_gemini.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/google_genai/inputs/books.xml b/examples/google_genai/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/google_genai/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/google_genai/inputs/example.json b/examples/google_genai/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/google_genai/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/google_genai/inputs/plain_html_example.txt b/examples/google_genai/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/google_genai/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/google_genai/inputs/username.csv b/examples/google_genai/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/google_genai/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/google_genai/json_scraper_gemini.py b/examples/google_genai/json_scraper_gemini.py deleted file mode 100644 index 343f1d42..00000000 --- a/examples/google_genai/json_scraper_gemini.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/google_genai/json_scraper_multi_gemini.py b/examples/google_genai/json_scraper_multi_gemini.py deleted file mode 100644 index 573faa97..00000000 --- a/examples/google_genai/json_scraper_multi_gemini.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Module for showing how JSONScraperMultiGraph multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, - "library": "beautifulsoup" -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/google_genai/rate_limit_gemini.py b/examples/google_genai/rate_limit_gemini.py deleted file mode 100644 index f3e2c555..00000000 --- a/examples/google_genai/rate_limit_gemini.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -import os -from dotenv import load_dotenv -from scrapegraphai.utils import prettify_exec_info -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - "rate_limit": { - "requests_per_second": 1 - } - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - # also accepts a string with the already downloaded HTML code - source="https://www.wired.com", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/readme.md b/examples/google_genai/readme.md deleted file mode 100644 index 7e06773d..00000000 --- a/examples/google_genai/readme.md +++ /dev/null @@ -1 +0,0 @@ -This folder contains an example of how to use ScrapeGraph-AI with Gemini, a large language model (LLM) from Google AI. The example shows how to extract information from a website using a natural language prompt. \ No newline at end of file diff --git a/examples/google_genai/scrape_plain_text_gemini.py b/examples/google_genai/scrape_plain_text_gemini.py deleted file mode 100644 index f554cede..00000000 --- a/examples/google_genai/scrape_plain_text_gemini.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - "temperature": 0, - "streaming": True - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/scrape_xml_gemini.py b/examples/google_genai/scrape_xml_gemini.py deleted file mode 100644 index af8868ea..00000000 --- a/examples/google_genai/scrape_xml_gemini.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - "temperature": 0, - "streaming": True - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/script_generator_gemini.py b/examples/google_genai/script_generator_gemini.py deleted file mode 100644 index fdf61f87..00000000 --- a/examples/google_genai/script_generator_gemini.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, - "library": "beautifoulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -smart_scraper_graph = ScriptCreatorGraph( - prompt="List me all the news with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/script_multi_generator_gemini.py b/examples/google_genai/script_multi_generator_gemini.py deleted file mode 100644 index 3ef0e108..00000000 --- a/examples/google_genai/script_multi_generator_gemini.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, - "library": "beautifoulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/search_graph_gemini.py b/examples/google_genai/search_graph_gemini.py deleted file mode 100644 index d001b34d..00000000 --- a/examples/google_genai/search_graph_gemini.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - "temperature": 0, - "streaming": True - }, - "max_results": 5, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me all the regions of Italy.", - config=graph_config -) - -result = search_graph.run() -print(result) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_genai/search_graph_schema_gemini.py b/examples/google_genai/search_graph_schema_gemini.py deleted file mode 100644 index c55854c5..00000000 --- a/examples/google_genai/search_graph_schema_gemini.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Example of Search Graph -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_genai/search_link_graph_gemini.py b/examples/google_genai/search_link_graph_gemini.py deleted file mode 100644 index 084cea41..00000000 --- a/examples/google_genai/search_link_graph_gemini.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_genai/smart_scraper_gemini.py b/examples/google_genai/smart_scraper_gemini.py deleted file mode 100644 index cb59e34f..00000000 --- a/examples/google_genai/smart_scraper_gemini.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.utils import prettify_exec_info -from scrapegraphai.graphs import SmartScraperGraph -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - # also accepts a string with the already downloaded HTML code - source="https://www.wired.com", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/smart_scraper_lite_google_genai.py b/examples/google_genai/smart_scraper_lite_google_genai.py deleted file mode 100644 index 9b776735..00000000 --- a/examples/google_genai/smart_scraper_lite_google_genai.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("GOOGLE_API_KEY"), - "model": "gemini-pro", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/smart_scraper_multi_concat_gemini.py b/examples/google_genai/smart_scraper_multi_concat_gemini.py deleted file mode 100644 index bf6ee544..00000000 --- a/examples/google_genai/smart_scraper_multi_concat_gemini.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/google_genai/smart_scraper_multi_gemini.py b/examples/google_genai/smart_scraper_multi_gemini.py deleted file mode 100644 index db721db9..00000000 --- a/examples/google_genai/smart_scraper_multi_gemini.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/google_genai/smart_scraper_multi_lite_gemini.py b/examples/google_genai/smart_scraper_multi_lite_gemini.py deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/google_genai/smart_scraper_multi_lite_google_genai.py b/examples/google_genai/smart_scraper_multi_lite_google_genai.py deleted file mode 100644 index e14e2ceb..00000000 --- a/examples/google_genai/smart_scraper_multi_lite_google_genai.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("GOOGLE_API_KEY"), - "model": "gemini-pro", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/smart_scraper_schema_gemini.py b/examples/google_genai/smart_scraper_schema_gemini.py deleted file mode 100644 index 7037dc08..00000000 --- a/examples/google_genai/smart_scraper_schema_gemini.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" -import os -from typing import List -from pydantic import BaseModel, Field -from dotenv import load_dotenv -from scrapegraphai.utils import prettify_exec_info -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - # also accepts a string with the already downloaded HTML code - source="https://www.wired.com", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_genai/xml_scraper_gemini.py b/examples/google_genai/xml_scraper_gemini.py deleted file mode 100644 index 3c3dc342..00000000 --- a/examples/google_genai/xml_scraper_gemini.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") - diff --git a/examples/google_genai/xml_scraper_graph_multi_gemini.py b/examples/google_genai/xml_scraper_graph_multi_gemini.py deleted file mode 100644 index 15bc2485..00000000 --- a/examples/google_genai/xml_scraper_graph_multi_gemini.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_genai/gemini-pro", - }, -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_vertexai/.env.example b/examples/google_vertexai/.env.example deleted file mode 100644 index fc0dacb0..00000000 --- a/examples/google_vertexai/.env.example +++ /dev/null @@ -1 +0,0 @@ -GOOGLE_APIKEY="your google api key" diff --git a/examples/google_vertexai/code_generator_graph_vertex.py b/examples/google_vertexai/code_generator_graph_vertex.py deleted file mode 100644 index 28f40174..00000000 --- a/examples/google_vertexai/code_generator_graph_vertex.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" - -import os, json -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) \ No newline at end of file diff --git a/examples/google_vertexai/csv_scraper_gemini.py b/examples/google_vertexai/csv_scraper_gemini.py deleted file mode 100644 index e5de1f17..00000000 --- a/examples/google_vertexai/csv_scraper_gemini.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" - -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the csv file -# ************************************************ - -text = pd.read_csv("inputs/username.csv") - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_vertexai/csv_scraper_graph_multi_gemini.py b/examples/google_vertexai/csv_scraper_graph_multi_gemini.py deleted file mode 100644 index 1318acfb..00000000 --- a/examples/google_vertexai/csv_scraper_graph_multi_gemini.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" - -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_vertexai/custom_graph_gemini.py b/examples/google_vertexai/custom_graph_gemini.py deleted file mode 100644 index 7feff114..00000000 --- a/examples/google_vertexai/custom_graph_gemini.py +++ /dev/null @@ -1,84 +0,0 @@ -""" -Example of custom graph using Gemini Google model -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.models import Gemini -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import FetchNode, ParseNode, RAGNode, GenerateAnswerNode -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - "temperature": 0, - "streaming": True - }, -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = Gemini(graph_config["llm"]) - -# define the nodes for the graph -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], -) -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={"chunk_size": 4096} -) -rag_node = RAGNode( - input="user_prompt & (parsed_doc | doc)", - output=["relevant_chunks"], - node_config={"llm": llm_model}, -) -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={"llm": llm_model}, -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes={ - fetch_node, - parse_node, - rag_node, - generate_answer_node, - }, - edges={ - (fetch_node, parse_node), - (parse_node, rag_node), - (rag_node, generate_answer_node) - }, - entry_point=fetch_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "List me the projects with their description", - "url": "https://perinim.github.io/projects/" -}) - -# get the answer from the result -result = result.get("answer", "No answer found.") -print(result) diff --git a/examples/google_vertexai/depth_search_graph_gemini.py b/examples/google_vertexai/depth_search_graph_gemini.py deleted file mode 100644 index 13bba630..00000000 --- a/examples/google_vertexai/depth_search_graph_gemini.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/google_vertexai/document_scraper_vertex.py b/examples/google_vertexai/document_scraper_vertex.py deleted file mode 100644 index 58f79a91..00000000 --- a/examples/google_vertexai/document_scraper_vertex.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/google_vertexai/inputs/books.xml b/examples/google_vertexai/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/google_vertexai/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/google_vertexai/inputs/example.json b/examples/google_vertexai/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/google_vertexai/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/google_vertexai/inputs/plain_html_example.txt b/examples/google_vertexai/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/google_vertexai/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/google_vertexai/inputs/username.csv b/examples/google_vertexai/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/google_vertexai/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/google_vertexai/json_scraper_gemini.py b/examples/google_vertexai/json_scraper_gemini.py deleted file mode 100644 index 8e9f5a9f..00000000 --- a/examples/google_vertexai/json_scraper_gemini.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/google_vertexai/json_scraper_multi_gemini.py b/examples/google_vertexai/json_scraper_multi_gemini.py deleted file mode 100644 index b9dc2e93..00000000 --- a/examples/google_vertexai/json_scraper_multi_gemini.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Module for showing how JSONScraperMultiGraph multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, - "library": "beautifulsoup" -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/google_vertexai/rate_limit_gemini.py b/examples/google_vertexai/rate_limit_gemini.py deleted file mode 100644 index c5f15a35..00000000 --- a/examples/google_vertexai/rate_limit_gemini.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.utils import prettify_exec_info -from scrapegraphai.graphs import SmartScraperGraph -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - "rate_limit": { - "requests_per_second": 1 - } - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - # also accepts a string with the already downloaded HTML code - source="https://www.wired.com", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/readme.md b/examples/google_vertexai/readme.md deleted file mode 100644 index 7e06773d..00000000 --- a/examples/google_vertexai/readme.md +++ /dev/null @@ -1 +0,0 @@ -This folder contains an example of how to use ScrapeGraph-AI with Gemini, a large language model (LLM) from Google AI. The example shows how to extract information from a website using a natural language prompt. \ No newline at end of file diff --git a/examples/google_vertexai/scrape_plain_text_gemini.py b/examples/google_vertexai/scrape_plain_text_gemini.py deleted file mode 100644 index b910330a..00000000 --- a/examples/google_vertexai/scrape_plain_text_gemini.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - "temperature": 0, - "streaming": True - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/scrape_xml_gemini.py b/examples/google_vertexai/scrape_xml_gemini.py deleted file mode 100644 index 0b6563a4..00000000 --- a/examples/google_vertexai/scrape_xml_gemini.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from XML documents -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - "temperature": 0, - "streaming": True - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/script_generator_gemini.py b/examples/google_vertexai/script_generator_gemini.py deleted file mode 100644 index 83bcb978..00000000 --- a/examples/google_vertexai/script_generator_gemini.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, - "library": "beautifoulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -smart_scraper_graph = ScriptCreatorGraph( - prompt="List me all the news with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/script_multi_generator_gemini.py b/examples/google_vertexai/script_multi_generator_gemini.py deleted file mode 100644 index 8ab3564e..00000000 --- a/examples/google_vertexai/script_multi_generator_gemini.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, - "library": "beautifoulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/search_graph_gemini.py b/examples/google_vertexai/search_graph_gemini.py deleted file mode 100644 index 1c86f322..00000000 --- a/examples/google_vertexai/search_graph_gemini.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Example of Search Graph -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - "temperature": 0, - "streaming": True - }, - "max_results": 5, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me all the regions of Italy.", - config=graph_config -) - -result = search_graph.run() -print(result) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_vertexai/search_graph_schema_gemini.py b/examples/google_vertexai/search_graph_schema_gemini.py deleted file mode 100644 index 54586c7e..00000000 --- a/examples/google_vertexai/search_graph_schema_gemini.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Example of Search Graph -""" - -import os -from dotenv import load_dotenv -load_dotenv() - -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -from pydantic import BaseModel, Field -from typing import List - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_vertexai/search_link_graph_gemini.py b/examples/google_vertexai/search_link_graph_gemini.py deleted file mode 100644 index d351b843..00000000 --- a/examples/google_vertexai/search_link_graph_gemini.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/google_vertexai/smart_scraper_gemini.py b/examples/google_vertexai/smart_scraper_gemini.py deleted file mode 100644 index 4ed7c352..00000000 --- a/examples/google_vertexai/smart_scraper_gemini.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.utils import prettify_exec_info -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - # also accepts a string with the already downloaded HTML code - source="https://www.wired.com", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/smart_scraper_lite_google_vertexai.py b/examples/google_vertexai/smart_scraper_lite_google_vertexai.py deleted file mode 100644 index eca61bbb..00000000 --- a/examples/google_vertexai/smart_scraper_lite_google_vertexai.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "project": os.getenv("GOOGLE_CLOUD_PROJECT"), - "location": "us-central1", - "model": "text-bison@001", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/google_vertexai/smart_scraper_multi_concat_gemini.py b/examples/google_vertexai/smart_scraper_multi_concat_gemini.py deleted file mode 100644 index c6874ff6..00000000 --- a/examples/google_vertexai/smart_scraper_multi_concat_gemini.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/google_vertexai/smart_scraper_multi_gemini.py b/examples/google_vertexai/smart_scraper_multi_gemini.py deleted file mode 100644 index ffbd6f47..00000000 --- a/examples/google_vertexai/smart_scraper_multi_gemini.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import os, json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/google_vertexai/smart_scraper_multi_lite_google_vertexai.py b/examples/google_vertexai/smart_scraper_multi_lite_google_vertexai.py deleted file mode 100644 index 5c293416..00000000 --- a/examples/google_vertexai/smart_scraper_multi_lite_google_vertexai.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "project": os.getenv("GOOGLE_CLOUD_PROJECT"), - "location": "us-central1", - "model": "text-bison@001", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/smart_scraper_multi_lite_vertex.py b/examples/google_vertexai/smart_scraper_multi_lite_vertex.py deleted file mode 100644 index 60ff3638..00000000 --- a/examples/google_vertexai/smart_scraper_multi_lite_vertex.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "project": os.getenv("GOOGLE_CLOUD_PROJECT"), - "location": "us-central1", - "model": "text-bison@001", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/smart_scraper_schema_gemini.py b/examples/google_vertexai/smart_scraper_schema_gemini.py deleted file mode 100644 index 541ce9aa..00000000 --- a/examples/google_vertexai/smart_scraper_schema_gemini.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" - -import os -from typing import List -from pydantic import BaseModel, Field -from dotenv import load_dotenv -from scrapegraphai.utils import prettify_exec_info -from scrapegraphai.graphs import SmartScraperGraph -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - # also accepts a string with the already downloaded HTML code - source="https://www.wired.com", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/google_vertexai/xml_scraper_gemini.py b/examples/google_vertexai/xml_scraper_gemini.py deleted file mode 100644 index de0e084f..00000000 --- a/examples/google_vertexai/xml_scraper_gemini.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") - diff --git a/examples/google_vertexai/xml_scraper_graph_multi_gemini.py b/examples/google_vertexai/xml_scraper_graph_multi_gemini.py deleted file mode 100644 index 3b7562d3..00000000 --- a/examples/google_vertexai/xml_scraper_graph_multi_gemini.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -gemini_key = os.getenv("GOOGLE_APIKEY") - -graph_config = { - "llm": { - "api_key": gemini_key, - "model": "google_vertexai/gemini-1.5-pro", - }, -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/groq/.env.example b/examples/groq/.env.example deleted file mode 100644 index c934d4fa..00000000 --- a/examples/groq/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -GROQ_APIKEY= "your groq key" -OPENAI_APIKEY="your openai api key" \ No newline at end of file diff --git a/examples/groq/code_generator_graph_groq.py b/examples/groq/code_generator_graph_groq.py deleted file mode 100644 index cf03d96c..00000000 --- a/examples/groq/code_generator_graph_groq.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) diff --git a/examples/groq/csv_scraper_graph_multi_groq.py b/examples/groq/csv_scraper_graph_multi_groq.py deleted file mode 100644 index e0343f31..00000000 --- a/examples/groq/csv_scraper_graph_multi_groq.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "headless": False -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/groq/csv_scraper_groq.py b/examples/groq/csv_scraper_groq.py deleted file mode 100644 index 6c36b4c4..00000000 --- a/examples/groq/csv_scraper_groq.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, -} -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/groq/custom_graph_groq.py b/examples/groq/custom_graph_groq.py deleted file mode 100644 index ea35137f..00000000 --- a/examples/groq/custom_graph_groq.py +++ /dev/null @@ -1,99 +0,0 @@ -""" -Example of custom graph using existing nodes -""" -import os -from dotenv import load_dotenv -from langchain_openai import ChatOpenAI -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import FetchNode, ParseNode, GenerateAnswerNode, RobotsNode -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = ChatOpenAI(graph_config["llm"]) - -# define the nodes for the graph -robot_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={ - "llm_model": llm_model, - "force_scraping": True, - "verbose": True, - } -) - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "verbose": True, - "headless": True, - } -) -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={ - "chunk_size": 4096, - "verbose": True, - } -) - -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={ - "llm_model": llm_model, - "verbose": True, - } -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes=[ - robot_node, - fetch_node, - parse_node, - generate_answer_node, - ], - edges=[ - (robot_node, fetch_node), - (fetch_node, parse_node), - (parse_node, generate_answer_node) - ], - entry_point=robot_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "Describe the content", - "url": "https://example.com/" -}) - -# get the answer from the result -result = result.get("answer", "No answer found.") -print(result) diff --git a/examples/groq/depth_search_graph_groq.py b/examples/groq/depth_search_graph_groq.py deleted file mode 100644 index 2d1ed8b1..00000000 --- a/examples/groq/depth_search_graph_groq.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/groq/document_scraper_groq.py b/examples/groq/document_scraper_groq.py deleted file mode 100644 index 53c64f73..00000000 --- a/examples/groq/document_scraper_groq.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "verbose": True, - "headless": False -} - - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/groq/inputs/books.xml b/examples/groq/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/groq/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/groq/inputs/example.json b/examples/groq/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/groq/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/groq/inputs/plain_html_example.txt b/examples/groq/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/groq/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/groq/inputs/username.csv b/examples/groq/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/groq/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/groq/json_scraper_groq.py b/examples/groq/json_scraper_groq.py deleted file mode 100644 index cac0f10d..00000000 --- a/examples/groq/json_scraper_groq.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/groq/json_scraper_multi_groq.py b/examples/groq/json_scraper_multi_groq.py deleted file mode 100644 index df3b9276..00000000 --- a/examples/groq/json_scraper_multi_groq.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Module for showing how JSONScraperMultiGraph multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "library": "beautifulsoup" -} -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/groq/rate_limit_groq.py b/examples/groq/rate_limit_groq.py deleted file mode 100644 index 8e59115f..00000000 --- a/examples/groq/rate_limit_groq.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0, - "rate_limit": { - "requests_per_second": 1 - } - }, - "headless": False -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/groq/scrape_plain_text_groq.py b/examples/groq/scrape_plain_text_groq.py deleted file mode 100644 index c4e4065d..00000000 --- a/examples/groq/scrape_plain_text_groq.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "verbose": True, - "headless": False -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/groq/script_generator_groq.py b/examples/groq/script_generator_groq.py deleted file mode 100644 index 08550044..00000000 --- a/examples/groq/script_generator_groq.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "library": "beautifulsoup" -} -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/groq/script_multi_generator_groq.py b/examples/groq/script_multi_generator_groq.py deleted file mode 100644 index 31f4041e..00000000 --- a/examples/groq/script_multi_generator_groq.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/groq/search_graph_groq.py b/examples/groq/search_graph_groq.py deleted file mode 100644 index ec971e37..00000000 --- a/examples/groq/search_graph_groq.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "headless": False -} - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/groq/search_graph_schema_groq.py b/examples/groq/search_graph_schema_groq.py deleted file mode 100644 index ae0de3ee..00000000 --- a/examples/groq/search_graph_schema_groq.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Example of Search Graph -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "headless": False -} - - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/groq/search_link_graph_groq.py b/examples/groq/search_link_graph_groq.py deleted file mode 100644 index 5d82f37f..00000000 --- a/examples/groq/search_link_graph_groq.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "headless": False -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/groq/smart_scraper_groq.py b/examples/groq/smart_scraper_groq.py deleted file mode 100644 index 4ac32678..00000000 --- a/examples/groq/smart_scraper_groq.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/groq/smart_scraper_lite_groq.py b/examples/groq/smart_scraper_lite_groq.py deleted file mode 100644 index 5fe6022f..00000000 --- a/examples/groq/smart_scraper_lite_groq.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("GROQ_API_KEY"), - "model": "mixtral-8x7b-32768", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/groq/smart_scraper_multi_concat_groq.py b/examples/groq/smart_scraper_multi_concat_groq.py deleted file mode 100644 index 79c262a1..00000000 --- a/examples/groq/smart_scraper_multi_concat_groq.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "headless": False -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/groq/smart_scraper_multi_groq.py b/examples/groq/smart_scraper_multi_groq.py deleted file mode 100644 index fec8fbb5..00000000 --- a/examples/groq/smart_scraper_multi_groq.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "verbose": True, - "headless": False -} -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/groq/smart_scraper_multi_lite_groq.py b/examples/groq/smart_scraper_multi_lite_groq.py deleted file mode 100644 index 9c8e4d1d..00000000 --- a/examples/groq/smart_scraper_multi_lite_groq.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("GROQ_API_KEY"), - "model": "mixtral-8x7b-32768", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/groq/smart_scraper_schema_groq.py b/examples/groq/smart_scraper_schema_groq.py deleted file mode 100644 index bfa7ed3b..00000000 --- a/examples/groq/smart_scraper_schema_groq.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" -import os -from typing import List -from pydantic import BaseModel, Field -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "headless": False -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/groq/xml_scraper_graph_multi_groq.py b/examples/groq/xml_scraper_graph_multi_groq.py deleted file mode 100644 index 09c7483f..00000000 --- a/examples/groq/xml_scraper_graph_multi_groq.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "headless": False -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/groq/xml_scraper_groq.py b/examples/groq/xml_scraper_groq.py deleted file mode 100644 index cb1ca8d7..00000000 --- a/examples/groq/xml_scraper_groq.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -groq_key = os.getenv("GROQ_APIKEY") - -graph_config = { - "llm": { - "model": "groq/gemma-7b-it", - "api_key": groq_key, - "temperature": 0 - }, - "verbose": True, - "headless": False -} -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") - diff --git a/examples/huggingfacehub/code_generator_graph_huggingfacehub.py b/examples/huggingfacehub/code_generator_graph_huggingfacehub.py deleted file mode 100644 index 4ff0d67e..00000000 --- a/examples/huggingfacehub/code_generator_graph_huggingfacehub.py +++ /dev/null @@ -1,71 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" - -import os, json -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -graph_config = { - "llm": { - "model_instance": llm_model_instance - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) \ No newline at end of file diff --git a/examples/huggingfacehub/csv_scraper_graph_multi_huggingfacehub.py b/examples/huggingfacehub/csv_scraper_graph_multi_huggingfacehub.py deleted file mode 100644 index 48b04dab..00000000 --- a/examples/huggingfacehub/csv_scraper_graph_multi_huggingfacehub.py +++ /dev/null @@ -1,68 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" - -import os -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/huggingfacehub/csv_scraper_huggingfacehub.py b/examples/huggingfacehub/csv_scraper_huggingfacehub.py deleted file mode 100644 index 18ce1194..00000000 --- a/examples/huggingfacehub/csv_scraper_huggingfacehub.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" - -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/huggingfacehub/custom_graph_huggingfacehub.py b/examples/huggingfacehub/custom_graph_huggingfacehub.py deleted file mode 100644 index 06b2f089..00000000 --- a/examples/huggingfacehub/custom_graph_huggingfacehub.py +++ /dev/null @@ -1,121 +0,0 @@ -""" -Example of custom graph using existing nodes -""" - -import os -from dotenv import load_dotenv -from langchain_openai import OpenAIEmbeddings -from langchain_openai import ChatOpenAI -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import FetchNode, ParseNode, RAGNode, GenerateAnswerNode, RobotsNode -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = OpenAI(graph_config["llm"]) -embedder = OpenAIEmbeddings(api_key=llm_model.openai_api_key) - -# define the nodes for the graph -robot_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={ - "llm_model": llm_model, - "force_scraping": True, - "verbose": True, - } -) - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "verbose": True, - "headless": True, - } -) -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={ - "chunk_size": 4096, - "verbose": True, - } -) -rag_node = RAGNode( - input="user_prompt & (parsed_doc | doc)", - output=["relevant_chunks"], - node_config={ - "llm_model": llm_model, - "embedder_model": embedder, - "verbose": True, - } -) -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={ - "llm_model": llm_model, - "verbose": True, - } -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes=[ - robot_node, - fetch_node, - parse_node, - rag_node, - generate_answer_node, - ], - edges=[ - (robot_node, fetch_node), - (fetch_node, parse_node), - (parse_node, rag_node), - (rag_node, generate_answer_node) - ], - entry_point=robot_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "Describe the content", - "url": "https://example.com/" -}) - -# get the answer from the result -result = result.get("answer", "No answer found.") -print(result) diff --git a/examples/huggingfacehub/depth_search_graph_huggingfacehub.py b/examples/huggingfacehub/depth_search_graph_huggingfacehub.py deleted file mode 100644 index 48df3e37..00000000 --- a/examples/huggingfacehub/depth_search_graph_huggingfacehub.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -graph_config = { - "llm": {"model_instance": llm_model_instance}, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/huggingfacehub/document_scraper_huggingfacehub.py b/examples/huggingfacehub/document_scraper_huggingfacehub.py deleted file mode 100644 index 5992f077..00000000 --- a/examples/huggingfacehub/document_scraper_huggingfacehub.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -# ************************************************ -# Define the configuration for the graph -# ************************************************ -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/huggingfacehub/inputs/books.xml b/examples/huggingfacehub/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/huggingfacehub/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/huggingfacehub/inputs/example.json b/examples/huggingfacehub/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/huggingfacehub/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/huggingfacehub/inputs/plain_html_example.txt b/examples/huggingfacehub/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/huggingfacehub/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/huggingfacehub/inputs/username.csv b/examples/huggingfacehub/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/huggingfacehub/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/huggingfacehub/json_scraper_huggingfacehub.py b/examples/huggingfacehub/json_scraper_huggingfacehub.py deleted file mode 100644 index f8223711..00000000 --- a/examples/huggingfacehub/json_scraper_huggingfacehub.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/huggingfacehub/json_scraper_multi_huggingfacehub.py b/examples/huggingfacehub/json_scraper_multi_huggingfacehub.py deleted file mode 100644 index c029431e..00000000 --- a/examples/huggingfacehub/json_scraper_multi_huggingfacehub.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Module for showing how PDFScraper multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/huggingfacehub/scrape_plain_text_huggingfacehub.py b/examples/huggingfacehub/scrape_plain_text_huggingfacehub.py deleted file mode 100644 index 76d32cda..00000000 --- a/examples/huggingfacehub/scrape_plain_text_huggingfacehub.py +++ /dev/null @@ -1,68 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/huggingfacehub/script_generator_huggingfacehub.py b/examples/huggingfacehub/script_generator_huggingfacehub.py deleted file mode 100644 index a3fcaaf4..00000000 --- a/examples/huggingfacehub/script_generator_huggingfacehub.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') -# ************************************************ -# Initialize the model instances -# ************************************************ - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/huggingfacehub/script_multi_generator_huggingfacehub.py b/examples/huggingfacehub/script_multi_generator_huggingfacehub.py deleted file mode 100644 index 0ee89189..00000000 --- a/examples/huggingfacehub/script_multi_generator_huggingfacehub.py +++ /dev/null @@ -1,66 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/huggingfacehub/search_graph_huggingfacehub.py b/examples/huggingfacehub/search_graph_huggingfacehub.py deleted file mode 100644 index 7c4a0c43..00000000 --- a/examples/huggingfacehub/search_graph_huggingfacehub.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Example of Search Graph -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/huggingfacehub/search_link_graph_huggingfacehub.py b/examples/huggingfacehub/search_link_graph_huggingfacehub.py deleted file mode 100644 index 75b41282..00000000 --- a/examples/huggingfacehub/search_link_graph_huggingfacehub.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Example of Search Graph -""" -import os -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -# ************************************************ - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/huggingfacehub/smart_scraper_huggingfacehub.py b/examples/huggingfacehub/smart_scraper_huggingfacehub.py deleted file mode 100644 index a50b574e..00000000 --- a/examples/huggingfacehub/smart_scraper_huggingfacehub.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper using Azure OpenAI Key -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - - -## required environment variable in .env -#HUGGINGFACEHUB_API_TOKEN -load_dotenv() - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') -# ************************************************ -# Initialize the model instances -# ************************************************ - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the events, with the following fields: company_name, event_name, event_start_date, event_start_time, event_end_date, event_end_time, location, event_mode, event_category, third_party_redirect, no_of_days, time_in_hours, hosted_or_attending, refreshments_type, registration_available, registration_link", - # also accepts a string with the already downloaded HTML code - source="https://www.hmhco.com/event", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - - diff --git a/examples/huggingfacehub/smart_scraper_lite_huggingfacehub.py b/examples/huggingfacehub/smart_scraper_lite_huggingfacehub.py deleted file mode 100644 index 4faa8a47..00000000 --- a/examples/huggingfacehub/smart_scraper_lite_huggingfacehub.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("HUGGINGFACEHUB_API_TOKEN"), - "model": "huggingfacehub/meta-llama/Llama-2-70b-chat-hf", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/huggingfacehub/smart_scraper_multi_concat_huggingfacehub.py b/examples/huggingfacehub/smart_scraper_multi_concat_huggingfacehub.py deleted file mode 100644 index 3f2d7135..00000000 --- a/examples/huggingfacehub/smart_scraper_multi_concat_huggingfacehub.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') -# ************************************************ -# Initialize the model instances -# ************************************************ - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/huggingfacehub/smart_scraper_multi_huggingfacehub.py b/examples/huggingfacehub/smart_scraper_multi_huggingfacehub.py deleted file mode 100644 index 046883a2..00000000 --- a/examples/huggingfacehub/smart_scraper_multi_huggingfacehub.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import os, json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/huggingfacehub/smart_scraper_multi_lite_huggingfacehub.py b/examples/huggingfacehub/smart_scraper_multi_lite_huggingfacehub.py deleted file mode 100644 index 2d7a3a45..00000000 --- a/examples/huggingfacehub/smart_scraper_multi_lite_huggingfacehub.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("HUGGINGFACEHUB_API_TOKEN"), - "model": "huggingfacehub/meta-llama/Llama-2-70b-chat-hf", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/huggingfacehub/smart_scraper_multi_lite_uhggingfacehub.py b/examples/huggingfacehub/smart_scraper_multi_lite_uhggingfacehub.py deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/huggingfacehub/smart_scraper_schema_huggingfacehub.py b/examples/huggingfacehub/smart_scraper_schema_huggingfacehub.py deleted file mode 100644 index 31719697..00000000 --- a/examples/huggingfacehub/smart_scraper_schema_huggingfacehub.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper using Azure OpenAI Key -""" - -import os -from dotenv import load_dotenv -from typing import Dict - -from pydantic import BaseModel -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str - description: str - -class Projects(BaseModel): - Projects: Dict[str, Project] - -## required environment variable in .env -#HUGGINGFACEHUB_API_TOKEN -load_dotenv() - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') -# ************************************************ -# Initialize the model instances -# ************************************************ - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/huggingfacehub/xml_scraper_graph_multi_huggingfacehub.py b/examples/huggingfacehub/xml_scraper_graph_multi_huggingfacehub.py deleted file mode 100644 index 1a244b86..00000000 --- a/examples/huggingfacehub/xml_scraper_graph_multi_huggingfacehub.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" - -import os -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/huggingfacehub/xml_scraper_huggingfacehub.py b/examples/huggingfacehub/xml_scraper_huggingfacehub.py deleted file mode 100644 index ddd73b5f..00000000 --- a/examples/huggingfacehub/xml_scraper_huggingfacehub.py +++ /dev/null @@ -1,68 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -from langchain_community.llms import HuggingFaceEndpoint -from langchain_community.embeddings import HuggingFaceInferenceAPIEmbeddings - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -HUGGINGFACEHUB_API_TOKEN = os.getenv('HUGGINGFACEHUB_API_TOKEN') - -repo_id = "mistralai/Mistral-7B-Instruct-v0.2" - -llm_model_instance = HuggingFaceEndpoint( - repo_id=repo_id, max_length=128, temperature=0.5, token=HUGGINGFACEHUB_API_TOKEN -) - -embedder_model_instance = HuggingFaceInferenceAPIEmbeddings( - api_key=HUGGINGFACEHUB_API_TOKEN, model_name="sentence-transformers/all-MiniLM-l6-v2" -) - -graph_config = { - "llm": {"model_instance": llm_model_instance}, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") - diff --git a/examples/integrations/indexify_node_example.py b/examples/integrations/indexify_node_example.py deleted file mode 100644 index 61db52d2..00000000 --- a/examples/integrations/indexify_node_example.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" - -import os, json -from typing import List - -from dotenv import load_dotenv -load_dotenv() - -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.integrations import IndexifyNode - - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Image(BaseModel): - url: str = Field(description="The url of the image") - -class Images(BaseModel): - images: List[Image] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key":openai_key, - "model": "openai/gpt-3.5-turbo", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Define the custom nodes for the graph -# ************************************************ - -indexify_node = IndexifyNode( - input="answer & img_urls", - output=["is_indexed"], - node_config={ - "verbose": True - } -) - -# ************************************************ -# Create the SmartScraperGraph instance -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the images with their url", - source="https://giphy.com/", - schema=Images, - config=graph_config -) - -# Add the custom node to the graph -smart_scraper_graph.append_node(indexify_node) - -# ************************************************ -# Run the SmartScraperGraph -# ************************************************ - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=2)) diff --git a/examples/json_scraper_graph/.env.example b/examples/json_scraper_graph/.env.example new file mode 100644 index 00000000..f1862149 --- /dev/null +++ b/examples/json_scraper_graph/.env.example @@ -0,0 +1,11 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# JSON Scraper Settings +MAX_DEPTH=3 +TIMEOUT=30 \ No newline at end of file diff --git a/examples/json_scraper_graph/README.md b/examples/json_scraper_graph/README.md new file mode 100644 index 00000000..217875ff --- /dev/null +++ b/examples/json_scraper_graph/README.md @@ -0,0 +1,30 @@ +# JSON Scraper Graph Example + +This example demonstrates how to use Scrapegraph-ai to extract and process JSON data from web sources. + +## Features + +- JSON data extraction +- Schema validation +- Data transformation +- Structured output + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import JsonScraperGraph + +graph = JsonScraperGraph() +json_data = graph.scrape("https://api.example.com/data") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/anthropic/inputs/example.json b/examples/json_scraper_graph/ollama/inputs/example.json similarity index 100% rename from examples/anthropic/inputs/example.json rename to examples/json_scraper_graph/ollama/inputs/example.json diff --git a/examples/local_models/json_scraper_multi_ollama.py b/examples/json_scraper_graph/ollama/json_scraper_multi_ollama.py similarity index 100% rename from examples/local_models/json_scraper_multi_ollama.py rename to examples/json_scraper_graph/ollama/json_scraper_multi_ollama.py diff --git a/examples/local_models/json_scraper_ollama.py b/examples/json_scraper_graph/ollama/json_scraper_ollama.py similarity index 100% rename from examples/local_models/json_scraper_ollama.py rename to examples/json_scraper_graph/ollama/json_scraper_ollama.py diff --git a/examples/azure/inputs/example.json b/examples/json_scraper_graph/openai/inputs/example.json similarity index 100% rename from examples/azure/inputs/example.json rename to examples/json_scraper_graph/openai/inputs/example.json diff --git a/examples/openai/json_scraper_multi_openai.py b/examples/json_scraper_graph/openai/json_scraper_multi_openai.py similarity index 100% rename from examples/openai/json_scraper_multi_openai.py rename to examples/json_scraper_graph/openai/json_scraper_multi_openai.py diff --git a/examples/openai/json_scraper_openai.py b/examples/json_scraper_graph/openai/json_scraper_openai.py similarity index 100% rename from examples/openai/json_scraper_openai.py rename to examples/json_scraper_graph/openai/json_scraper_openai.py diff --git a/examples/openai/md_scraper_openai.py b/examples/json_scraper_graph/openai/md_scraper_openai.py similarity index 100% rename from examples/openai/md_scraper_openai.py rename to examples/json_scraper_graph/openai/md_scraper_openai.py diff --git a/examples/openai/omni_scraper_openai.py b/examples/json_scraper_graph/openai/omni_scraper_openai.py similarity index 100% rename from examples/openai/omni_scraper_openai.py rename to examples/json_scraper_graph/openai/omni_scraper_openai.py diff --git a/examples/local_models/inputs/books.xml b/examples/local_models/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/local_models/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/local_models/inputs/example.json b/examples/local_models/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/local_models/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/local_models/inputs/plain_html_example.txt b/examples/local_models/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/local_models/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/local_models/inputs/username.csv b/examples/local_models/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/local_models/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/local_models/package-lock.json b/examples/local_models/package-lock.json deleted file mode 100644 index 4159e5cf..00000000 --- a/examples/local_models/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "local_models", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/examples/local_models/package.json b/examples/local_models/package.json deleted file mode 100644 index 0967ef42..00000000 --- a/examples/local_models/package.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/examples/local_models/scrape_plain_text_ollama.py b/examples/local_models/scrape_plain_text_ollama.py deleted file mode 100644 index fe24c2a9..00000000 --- a/examples/local_models/scrape_plain_text_ollama.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" - -import os -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ollama/mistral", - "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly - # "model_tokens": 2000, # set context length arbitrarily - "base_url": "http://localhost:11434", - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/local_models/search_link_graph_ollama.py b/examples/local_models/search_link_graph_ollama.py deleted file mode 100644 index 885b65e9..00000000 --- a/examples/local_models/search_link_graph_ollama.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -from scrapegraphai.graphs import SearchLinkGraph -from scrapegraphai.utils import prettify_exec_info -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ollama/llama3.1:8b", - "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly - # "base_url": "http://localhost:11434", # set ollama URL arbitrarily - }, - - "verbose": True, - "headless": False, - "filter_config": { - "diff_domain_filter": True, - # "img_exts": ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg', '.webp', '.ico'], - # "lang_indicators": ['lang=', '/fr', '/pt', '/es', '/de', '/jp', '/it'], - # "irrelevant_keywords": [ - # '/login', '/signup', '/register', '/contact', 'facebook.com', 'twitter.com', - # 'linkedin.com', 'instagram.com', '.js', '.css', '/wp-content/', '/wp-admin/', - # '/wp-includes/', '/wp-json/', '/wp-comments-post.php', ';amp', '/about', - # '/careers', '/jobs', '/privacy', '/terms', '/legal', '/faq', '/help', - # '.pdf', '.zip', '/news', '/files', '/downloads' - # ] - }, -} - -# ************************************************ -# Create the SearchLinkGraph instance and run it -# ************************************************ - -smart_scraper_graph = SearchLinkGraph( - source="https://sport.sky.it/nba?gr=www", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/local_models/smart_scraper_multi_concat_ollama.py b/examples/local_models/smart_scraper_multi_concat_ollama.py deleted file mode 100644 index 665b5db4..00000000 --- a/examples/local_models/smart_scraper_multi_concat_ollama.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "ollama/llama3.1", - "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly - "base_url": "http://localhost:11434", # set ollama URL arbitrarily - }, - "verbose": True, - "headless": False -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/mistral/.env.example b/examples/mistral/.env.example deleted file mode 100644 index cca63d1d..00000000 --- a/examples/mistral/.env.example +++ /dev/null @@ -1 +0,0 @@ -MISTRAL_API_KEY="YOUR MISTRAL API KEY" diff --git a/examples/mistral/code_generator_graph_mistral.py b/examples/mistral/code_generator_graph_mistral.py deleted file mode 100644 index 19af9aef..00000000 --- a/examples/mistral/code_generator_graph_mistral.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) diff --git a/examples/mistral/csv_scraper_graph_multi_mistral.py b/examples/mistral/csv_scraper_graph_multi_mistral.py deleted file mode 100644 index 608a8851..00000000 --- a/examples/mistral/csv_scraper_graph_multi_mistral.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/mistral/csv_scraper_mistral.py b/examples/mistral/csv_scraper_mistral.py deleted file mode 100644 index 6daa216c..00000000 --- a/examples/mistral/csv_scraper_mistral.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/mistral/custom_graph_mistral.py b/examples/mistral/custom_graph_mistral.py deleted file mode 100644 index bac1cd30..00000000 --- a/examples/mistral/custom_graph_mistral.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -Example of custom graph using existing nodes -""" -import os -from dotenv import load_dotenv -from langchain_mistralai import ChatMistralAI, MistralAIEmbeddings -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import FetchNode, ParseNode, RAGNode, GenerateAnswerNode, RobotsNode - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = ChatMistralAI(**graph_config["llm"]) -embedder = MistralAIEmbeddings(api_key=llm_model.mistral_api_key) - -# define the nodes for the graph -robot_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={ - "llm_model": llm_model, - "force_scraping": True, - "verbose": True, - } -) - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "verbose": True, - "headless": True, - } -) -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={ - "chunk_size": 4096, - "verbose": True, - } -) -rag_node = RAGNode( - input="user_prompt & (parsed_doc | doc)", - output=["relevant_chunks"], - node_config={ - "llm_model": llm_model, - "embedder_model": embedder, - "verbose": True, - } -) -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={ - "llm_model": llm_model, - "verbose": True, - } -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes=[ - robot_node, - fetch_node, - parse_node, - rag_node, - generate_answer_node, - ], - edges=[ - (robot_node, fetch_node), - (fetch_node, parse_node), - (parse_node, rag_node), - (rag_node, generate_answer_node) - ], - entry_point=robot_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "Describe the content", - "url": "https://example.com/" -}) - -# get the answer from the result -result = result.get("answer", "No answer found.") -print(result) diff --git a/examples/mistral/depth_search_graph_mistral.py b/examples/mistral/depth_search_graph_mistral.py deleted file mode 100644 index ae18ffba..00000000 --- a/examples/mistral/depth_search_graph_mistral.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/mistral/document_scraper_mistral.py b/examples/mistral/document_scraper_mistral.py deleted file mode 100644 index aa75e9c4..00000000 --- a/examples/mistral/document_scraper_mistral.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, -} - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) diff --git a/examples/mistral/inputs/books.xml b/examples/mistral/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/mistral/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/mistral/inputs/example.json b/examples/mistral/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/mistral/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/mistral/inputs/plain_html_example.txt b/examples/mistral/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/mistral/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/mistral/inputs/username.csv b/examples/mistral/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/mistral/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/mistral/json_scraper_mistral.py b/examples/mistral/json_scraper_mistral.py deleted file mode 100644 index 0b9be3ec..00000000 --- a/examples/mistral/json_scraper_mistral.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) diff --git a/examples/mistral/json_scraper_multi_mistral.py b/examples/mistral/json_scraper_multi_mistral.py deleted file mode 100644 index 1369eda7..00000000 --- a/examples/mistral/json_scraper_multi_mistral.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -Module for showing how PDFScraper multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - } -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/mistral/md_scraper_mistral.py b/examples/mistral/md_scraper_mistral.py deleted file mode 100644 index 135f08ba..00000000 --- a/examples/mistral/md_scraper_mistral.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using DocumentScraperGraph from MD documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the MD file -# ************************************************ - -FILE_NAME = "inputs/markdown_example.md" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, -} - -# ************************************************ -# Create the DocumentScraperGraph instance and run it -# ************************************************ - -md_scraper_graph = DocumentScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = md_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = md_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/mistral/rate_limit_mistral.py b/examples/mistral/rate_limit_mistral.py deleted file mode 100644 index 4bc0f6fb..00000000 --- a/examples/mistral/rate_limit_mistral.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -import os -import json -from scrapegraphai.graphs import SmartScraperGraph -from dotenv import load_dotenv - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "api_key": os.getenv("MISTRAL_API_KEY"), - "model": "mistralai/open-mistral-nemo", - "rate_limit": { - "requests_per_second": 1 - } - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me what does the company do, the name and a contact email.", - source="https://scrapegraphai.com/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/mistral/readme.md b/examples/mistral/readme.md deleted file mode 100644 index 6e13a97b..00000000 --- a/examples/mistral/readme.md +++ /dev/null @@ -1 +0,0 @@ -This folder contains examples of how to use ScrapeGraph-AI with Mistral, an LLM provider. The examples show how to extract information from a website using a natural language prompt. \ No newline at end of file diff --git a/examples/mistral/scrape_plain_text_mistral.py b/examples/mistral/scrape_plain_text_mistral.py deleted file mode 100644 index 131747c6..00000000 --- a/examples/mistral/scrape_plain_text_mistral.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/mistral/script_generator_mistral.py b/examples/mistral/script_generator_mistral.py deleted file mode 100644 index 74a81b46..00000000 --- a/examples/mistral/script_generator_mistral.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/mistral/script_generator_schema_mistral.py b/examples/mistral/script_generator_schema_mistral.py deleted file mode 100644 index 3ad46685..00000000 --- a/examples/mistral/script_generator_schema_mistral.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info -from pydantic import BaseModel, Field -from typing import List - -load_dotenv() - -# ************************************************ -# Define the schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "library": "beautifulsoup", - "verbose": True, -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config, - schema=Projects -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/mistral/script_multi_generator_mistral.py b/examples/mistral/script_multi_generator_mistral.py deleted file mode 100644 index d5869c53..00000000 --- a/examples/mistral/script_multi_generator_mistral.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "library": "beautifulsoup", - "verbose": True, -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/mistral/search_graph_mistral.py b/examples/mistral/search_graph_mistral.py deleted file mode 100644 index 983733e0..00000000 --- a/examples/mistral/search_graph_mistral.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "max_results": 2, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/mistral/search_graph_schema_mistral.py b/examples/mistral/search_graph_schema_mistral.py deleted file mode 100644 index 06a88ff7..00000000 --- a/examples/mistral/search_graph_schema_mistral.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Example of Search Graph -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "max_results": 2, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/mistral/search_link_graph_mistral.py b/examples/mistral/search_link_graph_mistral.py deleted file mode 100644 index 45d0c5f0..00000000 --- a/examples/mistral/search_link_graph_mistral.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchLinkGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SearchLinkGraph instance and run it -# ************************************************ - -smart_scraper_graph = SearchLinkGraph( - source="https://sport.sky.it/nba?gr=www", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/mistral/smart_scraper_lite_mistral.py b/examples/mistral/smart_scraper_lite_mistral.py deleted file mode 100644 index 390371f9..00000000 --- a/examples/mistral/smart_scraper_lite_mistral.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("MISTRAL_API_KEY"), - "model": "mistral/mistral-medium", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/mistral/smart_scraper_mistral.py b/examples/mistral/smart_scraper_mistral.py deleted file mode 100644 index a2f82504..00000000 --- a/examples/mistral/smart_scraper_mistral.py +++ /dev/null @@ -1,36 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "api_key": os.getenv("MISTRAL_API_KEY"), - "model": "mistralai/open-mistral-nemo", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me what does the company do, the name and a contact email.", - source="https://scrapegraphai.com/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/mistral/smart_scraper_multi_lite_mistral.py b/examples/mistral/smart_scraper_multi_lite_mistral.py deleted file mode 100644 index ce2d19bf..00000000 --- a/examples/mistral/smart_scraper_multi_lite_mistral.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("MISTRAL_API_KEY"), - "model": "mistral/mistral-medium", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/mistral/smart_scraper_multi_mistral.py b/examples/mistral/smart_scraper_multi_mistral.py deleted file mode 100644 index 7929f9cc..00000000 --- a/examples/mistral/smart_scraper_multi_mistral.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "verbose": True, - "headless": False, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/mistral/smart_scraper_schema_mistral.py b/examples/mistral/smart_scraper_schema_mistral.py deleted file mode 100644 index 3b129a89..00000000 --- a/examples/mistral/smart_scraper_schema_mistral.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key":mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) diff --git a/examples/mistral/xml_scraper_graph_multi_mistral.py b/examples/mistral/xml_scraper_graph_multi_mistral.py deleted file mode 100644 index 6db20ebf..00000000 --- a/examples/mistral/xml_scraper_graph_multi_mistral.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key":mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "verbose": True, - "headless": False, -} -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/mistral/xml_scraper_mistral.py b/examples/mistral/xml_scraper_mistral.py deleted file mode 100644 index 6d551c22..00000000 --- a/examples/mistral/xml_scraper_mistral.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, - "verbose":False, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/model_instance/.env.example b/examples/model_instance/.env.example deleted file mode 100644 index c5a7ed85..00000000 --- a/examples/model_instance/.env.example +++ /dev/null @@ -1 +0,0 @@ -MOONLIGHT_API_KEY="YOUR MOONLIGHT API KEY" \ No newline at end of file diff --git a/examples/model_instance/smart_scraper_with_model_instace.py b/examples/model_instance/smart_scraper_with_model_instace.py deleted file mode 100644 index b362414f..00000000 --- a/examples/model_instance/smart_scraper_with_model_instace.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper and model_instace -""" - -import os, json -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info -from langchain_community.chat_models.moonshot import MoonshotChat -from dotenv import load_dotenv -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -llm_instance_config = { - "model": "moonshot-v1-8k", - "base_url": "https://api.moonshot.cn/v1", - "moonshot_api_key": os.getenv("MOONLIGHT_API_KEY"), -} - - -llm_model_instance = MoonshotChat(**llm_instance_config) - -graph_config = { - "llm": { - "model_instance": llm_model_instance, - "model_tokens": 10000 - }, - "verbose": True, - "headless": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me what does the company do, the name and a contact email.", - source="https://scrapegraphai.com/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/moonshot/.env.example b/examples/moonshot/.env.example deleted file mode 100644 index c5a7ed85..00000000 --- a/examples/moonshot/.env.example +++ /dev/null @@ -1 +0,0 @@ -MOONLIGHT_API_KEY="YOUR MOONLIGHT API KEY" \ No newline at end of file diff --git a/examples/moonshot/code_generator_graph_moonshot.py b/examples/moonshot/code_generator_graph_moonshot.py deleted file mode 100644 index 58e6182b..00000000 --- a/examples/moonshot/code_generator_graph_moonshot.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" - -import os, json -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from langchain_community.chat_models.moonshot import MoonshotChat -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -llm_instance_config = { - "model": "moonshot-v1-8k", - "base_url": "https://api.moonshot.cn/v1", - "moonshot_api_key": os.getenv("MOONLIGHT_API_KEY"), -} - -llm_model_instance = MoonshotChat(**llm_instance_config) - -graph_config = { - "llm": { - "model_instance": llm_model_instance, - "model_tokens": 10000 - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) \ No newline at end of file diff --git a/examples/moonshot/document_scraper_moonshot.py b/examples/moonshot/document_scraper_moonshot.py deleted file mode 100644 index aa75e9c4..00000000 --- a/examples/moonshot/document_scraper_moonshot.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -mistral_key = os.getenv("MISTRAL_API_KEY") - -graph_config = { - "llm": { - "api_key": mistral_key, - "model": "mistralai/open-mistral-nemo", - }, -} - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) diff --git a/examples/moonshot/readme.md b/examples/moonshot/readme.md deleted file mode 100644 index 6b9b2f21..00000000 --- a/examples/moonshot/readme.md +++ /dev/null @@ -1 +0,0 @@ -This folder offer an example of how to use ScrapeGraph-AI with Moonshot and SmartScraperGraph. More usage examples can refer to openai exapmles. \ No newline at end of file diff --git a/examples/moonshot/smart_scraper_lite_moonshot.py b/examples/moonshot/smart_scraper_lite_moonshot.py deleted file mode 100644 index 509027fb..00000000 --- a/examples/moonshot/smart_scraper_lite_moonshot.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ANTHROPIC_API_KEY"), - "model": "anthropic/claude-3-haiku-20240307", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/moonshot/smart_scraper_multi_concat_moonshot.py b/examples/moonshot/smart_scraper_multi_concat_moonshot.py deleted file mode 100644 index 1e652db4..00000000 --- a/examples/moonshot/smart_scraper_multi_concat_moonshot.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from langchain_community.chat_models.moonshot import MoonshotChat -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -llm_instance_config = { - "model": "moonshot-v1-8k", - "base_url": "https://api.moonshot.cn/v1", - "moonshot_api_key": os.getenv("MOONLIGHT_API_KEY"), -} - - -llm_model_instance = MoonshotChat(**llm_instance_config) - -graph_config = { - "llm": { - "model_instance": llm_model_instance, - "model_tokens": 10000 - }, - "verbose": True, - "headless": True, -} - - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/moonshot/smart_scraper_multi_lite_moonshot.py b/examples/moonshot/smart_scraper_multi_lite_moonshot.py deleted file mode 100644 index b3e2b7be..00000000 --- a/examples/moonshot/smart_scraper_multi_lite_moonshot.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("MOONSHOT_API_KEY"), - "model": "moonshot/moonshot-v1-8b", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/moonshot/smart_scraper_with_moonshot.py b/examples/moonshot/smart_scraper_with_moonshot.py deleted file mode 100644 index 28635ba3..00000000 --- a/examples/moonshot/smart_scraper_with_moonshot.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper and model_instace -""" -import os -import json -from langchain_community.chat_models.moonshot import MoonshotChat -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -llm_instance_config = { - "model": "moonshot-v1-8k", - "base_url": "https://api.moonshot.cn/v1", - "moonshot_api_key": os.getenv("MOONLIGHT_API_KEY"), -} - - -llm_model_instance = MoonshotChat(**llm_instance_config) - -graph_config = { - "llm": { - "model_instance": llm_model_instance, - "model_tokens": 10000 - }, - "verbose": True, - "headless": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me what does the company do, the name and a contact email.", - source="https://scrapegraphai.com/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/code_generator_graph_nemotron.py b/examples/nemotron/code_generator_graph_nemotron.py deleted file mode 100644 index 5ccd9d9f..00000000 --- a/examples/nemotron/code_generator_graph_nemotron.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_APIKEY"), - "model": "nvidia/meta/llama3-70b-instruct", - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) diff --git a/examples/nemotron/csv_scraper_graph_multi_nemotron.py b/examples/nemotron/csv_scraper_graph_multi_nemotron.py deleted file mode 100644 index d5de6039..00000000 --- a/examples/nemotron/csv_scraper_graph_multi_nemotron.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -import pandas as pd -from dotenv import load_dotenv -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_APIKEY"), - "model": "nvidia/meta/llama3-70b-instruct", - } -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/nemotron/csv_scraper_nemotron.py b/examples/nemotron/csv_scraper_nemotron.py deleted file mode 100644 index 2d527450..00000000 --- a/examples/nemotron/csv_scraper_nemotron.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/nemotron/depth_search_graph_nemotron.py b/examples/nemotron/depth_search_graph_nemotron.py deleted file mode 100644 index edd80463..00000000 --- a/examples/nemotron/depth_search_graph_nemotron.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_KEY"), - "model": "claude-3-haiku-20240307", - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/nemotron/document_scraper_nemotron.py b/examples/nemotron/document_scraper_nemotron.py deleted file mode 100644 index 618047ee..00000000 --- a/examples/nemotron/document_scraper_nemotron.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, -} - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/nemotron/inputs/books.xml b/examples/nemotron/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/nemotron/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/nemotron/inputs/example.json b/examples/nemotron/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/nemotron/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/nemotron/inputs/markdown_example.md b/examples/nemotron/inputs/markdown_example.md deleted file mode 100644 index 85088f29..00000000 --- a/examples/nemotron/inputs/markdown_example.md +++ /dev/null @@ -1,35 +0,0 @@ -Marco Perini Toggle navigation - - * About - * Projects(current) - -Projects - -Competitions - - * CV - * ____ - -# Projects - - ![project thumbnail Rotary Pendulum RL -Open Source project aimed at controlling a real life rotary pendulum using RL -algorithms ](/projects/rotary-pendulum-rl/) - - ![project thumbnail DQN -Implementation from scratch Developed a Deep Q-Network algorithm to train a -simple and double pendulum ](https://github.com/PeriniM/DQN-SwingUp) - - ![project thumbnail Multi Agents HAED -University project which focuses on simulating a multi-agent system to perform -environment mapping. Agents, equipped with sensors, explore and record their -surroundings, considering uncertainties in their readings. -](https://github.com/PeriniM/Multi-Agents-HAED) - - ![project thumbnail Wireless ESC for Modular -Drones Modular drone architecture proposal and proof of concept. The project -received maximum grade. ](/projects/wireless-esc-drone/) - -© Copyright 2023 Marco Perini. Powered by Jekyll with -al-folio theme. Hosted by [GitHub -Pages](https://pages.github.com/). \ No newline at end of file diff --git a/examples/nemotron/inputs/plain_html_example.txt b/examples/nemotron/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/nemotron/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/nemotron/inputs/username.csv b/examples/nemotron/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/nemotron/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/nemotron/json_scraper_multi_nemotron.py b/examples/nemotron/json_scraper_multi_nemotron.py deleted file mode 100644 index 846c7f48..00000000 --- a/examples/nemotron/json_scraper_multi_nemotron.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -Module for showing how PDFScraper multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/nemotron/json_scraper_nemotron.py b/examples/nemotron/json_scraper_nemotron.py deleted file mode 100644 index a5479ca7..00000000 --- a/examples/nemotron/json_scraper_nemotron.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = json_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/nemotron/md_scraper_nemotron.py b/examples/nemotron/md_scraper_nemotron.py deleted file mode 100644 index 8e925c03..00000000 --- a/examples/nemotron/md_scraper_nemotron.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using DocumentScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/markdown_example.md" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, -} - -# ************************************************ -# Create the DocumentScraperGraph instance and run it -# ************************************************ - -md_scraper_graph = DocumentScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = md_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = md_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/nemotron/rate_limit_nemotron.py b/examples/nemotron/rate_limit_nemotron.py deleted file mode 100644 index 934c2036..00000000 --- a/examples/nemotron/rate_limit_nemotron.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_KEY"), - "model": "nvidia/meta/llama3-70b-instruct", - "rate_limit": { - "requests_per_second": 1 - } - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="Extract me the python code inside the page", - source="https://www.exploit-db.com/exploits/51447", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/scrape_plain_text_nemotron.py b/examples/nemotron/scrape_plain_text_nemotron.py deleted file mode 100644 index 315bae8e..00000000 --- a/examples/nemotron/scrape_plain_text_nemotron.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/script_generator_nemotron.py b/examples/nemotron/script_generator_nemotron.py deleted file mode 100644 index 2ff8176a..00000000 --- a/examples/nemotron/script_generator_nemotron.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/script_generator_schema_nemotron.py b/examples/nemotron/script_generator_schema_nemotron.py deleted file mode 100644 index 9516521a..00000000 --- a/examples/nemotron/script_generator_schema_nemotron.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from typing import List -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "library": "beautifulsoup", - "verbose": True, -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config, - schema=Projects -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/script_multi_generator_nemotron.py b/examples/nemotron/script_multi_generator_nemotron.py deleted file mode 100644 index 730fab8d..00000000 --- a/examples/nemotron/script_multi_generator_nemotron.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "library": "beautifulsoup", - "verbose": True, -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/search_graph_nemotron.py b/examples/nemotron/search_graph_nemotron.py deleted file mode 100644 index e57e9642..00000000 --- a/examples/nemotron/search_graph_nemotron.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "max_results": 2, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/nemotron/search_graph_schema_nemotron.py b/examples/nemotron/search_graph_schema_nemotron.py deleted file mode 100644 index 64fbf047..00000000 --- a/examples/nemotron/search_graph_schema_nemotron.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Example of Search Graph -""" - -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "max_results": 2, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/nemotron/search_link_graph_nemotron.py b/examples/nemotron/search_link_graph_nemotron.py deleted file mode 100644 index 50dce11b..00000000 --- a/examples/nemotron/search_link_graph_nemotron.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchLinkGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_APIKEY"), - "model": "nvidia/meta/llama3-70b-instruct", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SearchLinkGraph instance and run it -# ************************************************ - -smart_scraper_graph = SearchLinkGraph( - source="https://sport.sky.it/nba?gr=www", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/smart_scraper_lite_nemotron.py b/examples/nemotron/smart_scraper_lite_nemotron.py deleted file mode 100644 index 6c1d8528..00000000 --- a/examples/nemotron/smart_scraper_lite_nemotron.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_API_KEY"), - "model": "nemotron/nemotron-3.5-turbo", - "base_url": "http://127.0.0.1:3000/v1", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/smart_scraper_multi_concat_nemotron.py b/examples/nemotron/smart_scraper_multi_concat_nemotron.py deleted file mode 100644 index 3297fcbf..00000000 --- a/examples/nemotron/smart_scraper_multi_concat_nemotron.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_APIKEY"), - "model": "nvidia/meta/llama3-70b-instruct", - }, - "verbose": True, - "headless": False, -} -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/nemotron/smart_scraper_multi_lite_nemotron.py b/examples/nemotron/smart_scraper_multi_lite_nemotron.py deleted file mode 100644 index 7639d820..00000000 --- a/examples/nemotron/smart_scraper_multi_lite_nemotron.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_API_KEY"), - "model": "nemotron/nemotron-3-8b-chat", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/smart_scraper_multi_nemotron.py b/examples/nemotron/smart_scraper_multi_nemotron.py deleted file mode 100644 index 00306a96..00000000 --- a/examples/nemotron/smart_scraper_multi_nemotron.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "verbose": True, - "headless": False, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/nemotron/smart_scraper_nemotron.py b/examples/nemotron/smart_scraper_nemotron.py deleted file mode 100644 index 10ad42b7..00000000 --- a/examples/nemotron/smart_scraper_nemotron.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "api_key": os.getenv("NEMOTRON_KEY"), - "model": "nvidia/meta/llama3-70b-instruct", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="Extract me the python code inside the page", - source="https://www.exploit-db.com/exploits/51447", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/smart_scraper_schema_nemotron.py b/examples/nemotron/smart_scraper_schema_nemotron.py deleted file mode 100644 index 54dbce1f..00000000 --- a/examples/nemotron/smart_scraper_schema_nemotron.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SmartScraperGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key":nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) diff --git a/examples/nemotron/speech_graph_nemotron.py b/examples/nemotron/speech_graph_nemotron.py deleted file mode 100644 index 21f0d2b1..00000000 --- a/examples/nemotron/speech_graph_nemotron.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Basic example of scraping pipeline using SpeechSummaryGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SpeechGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define audio output path -# ************************************************ - -FILE_NAME = "website_summary.mp3" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -output_path = os.path.join(curr_dir, FILE_NAME) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, -} - -# ************************************************ -# Create the SpeechGraph instance and run it -# ************************************************ - -speech_graph = SpeechGraph( - prompt="Make a detailed audio summary of the projects.", - source="https://perinim.github.io/projects/", - config=graph_config, -) - -result = speech_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = speech_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/nemotron/xml_scraper_graph_nemotron.py b/examples/nemotron/xml_scraper_graph_nemotron.py deleted file mode 100644 index 753b0be5..00000000 --- a/examples/nemotron/xml_scraper_graph_nemotron.py +++ /dev/null @@ -1,60 +0,0 @@ -""" - -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key":nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "verbose": True, - "headless": False, -} -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/nemotron/xml_scraper_nemotron.py b/examples/nemotron/xml_scraper_nemotron.py deleted file mode 100644 index 5f7cb7d6..00000000 --- a/examples/nemotron/xml_scraper_nemotron.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -nemotron_key = os.getenv("NEMOTRON_APIKEY") - -graph_config = { - "llm": { - "api_key": nemotron_key, - "model": "nvidia/meta/llama3-70b-instruct", - }, - "verbose":False, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") - diff --git a/examples/omni_scraper_graph/.env.example b/examples/omni_scraper_graph/.env.example new file mode 100644 index 00000000..d5bb1b4d --- /dev/null +++ b/examples/omni_scraper_graph/.env.example @@ -0,0 +1,13 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# Omni Scraper Settings +DEFAULT_FORMAT=auto +TIMEOUT=60 +MAX_RETRIES=3 +USER_AGENT=Mozilla/5.0 \ No newline at end of file diff --git a/examples/omni_scraper_graph/README.md b/examples/omni_scraper_graph/README.md new file mode 100644 index 00000000..da5ab652 --- /dev/null +++ b/examples/omni_scraper_graph/README.md @@ -0,0 +1,30 @@ +# Omni Scraper Graph Example + +This example demonstrates how to use Scrapegraph-ai for universal web scraping across multiple data formats. + +## Features + +- Multi-format data extraction (JSON, XML, HTML, CSV) +- Automatic format detection +- Unified data output +- Content transformation + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import OmniScraperGraph + +graph = OmniScraperGraph() +data = graph.scrape("https://example.com/data") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/openai/omni_search_openai.py b/examples/omni_scraper_graph/omni_search_openai.py similarity index 100% rename from examples/openai/omni_search_openai.py rename to examples/omni_scraper_graph/omni_search_openai.py diff --git a/examples/oneapi/code_generator_graph_oneapi.py b/examples/oneapi/code_generator_graph_oneapi.py deleted file mode 100644 index 5f9808a3..00000000 --- a/examples/oneapi/code_generator_graph_oneapi.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" -import os -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) \ No newline at end of file diff --git a/examples/oneapi/csv_scraper_graph_multi_oneapi.py b/examples/oneapi/csv_scraper_graph_multi_oneapi.py deleted file mode 100644 index 7b5d8abd..00000000 --- a/examples/oneapi/csv_scraper_graph_multi_oneapi.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/oneapi/csv_scraper_oneapi.py b/examples/oneapi/csv_scraper_oneapi.py deleted file mode 100644 index a9fda090..00000000 --- a/examples/oneapi/csv_scraper_oneapi.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/oneapi/custom_graph_oneapi.py b/examples/oneapi/custom_graph_oneapi.py deleted file mode 100644 index 1e27dcf9..00000000 --- a/examples/oneapi/custom_graph_oneapi.py +++ /dev/null @@ -1,105 +0,0 @@ -""" -Example of custom graph using existing nodes -""" -from langchain_openai import OpenAIEmbeddings -from langchain_openai import ChatOpenAI -from scrapegraphai.graphs import BaseGraph -from scrapegraphai.nodes import FetchNode, ParseNode, RAGNode, GenerateAnswerNode, RobotsNode - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Define the graph nodes -# ************************************************ - -llm_model = ChatOpenAI(graph_config["llm"]) -embedder = OpenAIEmbeddings(api_key=llm_model.openai_api_key) - -# define the nodes for the graph -robot_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={ - "llm_model": llm_model, - "force_scraping": True, - "verbose": True, - } -) - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "verbose": True, - "headless": True, - } -) -parse_node = ParseNode( - input="doc", - output=["parsed_doc"], - node_config={ - "chunk_size": 4096, - "verbose": True, - } -) -rag_node = RAGNode( - input="user_prompt & (parsed_doc | doc)", - output=["relevant_chunks"], - node_config={ - "llm_model": llm_model, - "embedder_model": embedder, - "verbose": True, - } -) -generate_answer_node = GenerateAnswerNode( - input="user_prompt & (relevant_chunks | parsed_doc | doc)", - output=["answer"], - node_config={ - "llm_model": llm_model, - "verbose": True, - } -) - -# ************************************************ -# Create the graph by defining the connections -# ************************************************ - -graph = BaseGraph( - nodes=[ - robot_node, - fetch_node, - parse_node, - rag_node, - generate_answer_node, - ], - edges=[ - (robot_node, fetch_node), - (fetch_node, parse_node), - (parse_node, rag_node), - (rag_node, generate_answer_node) - ], - entry_point=robot_node -) - -# ************************************************ -# Execute the graph -# ************************************************ - -result, execution_info = graph.execute({ - "user_prompt": "Describe the content", - "url": "https://example.com/" -}) - -# get the answer from the result -result = result.get("answer", "No answer found.") -print(result) diff --git a/examples/oneapi/depth_search_graph_onenapi.py b/examples/oneapi/depth_search_graph_onenapi.py deleted file mode 100644 index 7a2e7f3e..00000000 --- a/examples/oneapi/depth_search_graph_onenapi.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/oneapi/document_scraper_oneapi.py b/examples/oneapi/document_scraper_oneapi.py deleted file mode 100644 index 99ffe295..00000000 --- a/examples/oneapi/document_scraper_oneapi.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -document_scraper example -""" -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/oneapi/inputs/books.xml b/examples/oneapi/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/oneapi/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/oneapi/inputs/example.json b/examples/oneapi/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/oneapi/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/oneapi/inputs/plain_html_example copy.txt b/examples/oneapi/inputs/plain_html_example copy.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/oneapi/inputs/plain_html_example copy.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/oneapi/inputs/plain_html_example.txt b/examples/oneapi/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/oneapi/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/oneapi/inputs/username.csv b/examples/oneapi/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/oneapi/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/oneapi/json_scraper_multi_oneapi.py b/examples/oneapi/json_scraper_multi_oneapi.py deleted file mode 100644 index fc1c4555..00000000 --- a/examples/oneapi/json_scraper_multi_oneapi.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Module for showing how PDFScraper multi works -""" -import os -import json -from scrapegraphai.graphs import JSONScraperMultiGraph - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/oneapi/json_scraper_oneapi.py b/examples/oneapi/json_scraper_oneapi.py deleted file mode 100644 index 2f89fc50..00000000 --- a/examples/oneapi/json_scraper_oneapi.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Read the JSON file -# ************************************************ - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = json_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/oneapi/rate_limit_oneapi.py b/examples/oneapi/rate_limit_oneapi.py deleted file mode 100644 index abd2f9c7..00000000 --- a/examples/oneapi/rate_limit_oneapi.py +++ /dev/null @@ -1,41 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - "rate_limit": { - "requests_per_second": 1 - } - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the titles", - # also accepts a string with the already downloaded HTML code - source="https://www.wired.com/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/oneapi/scrape_plain_text_oneapi.py b/examples/oneapi/scrape_plain_text_oneapi.py deleted file mode 100644 index 268d2b0d..00000000 --- a/examples/oneapi/scrape_plain_text_oneapi.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/oneapi/script_generator_oneapi.py b/examples/oneapi/script_generator_oneapi.py deleted file mode 100644 index 3876eb34..00000000 --- a/examples/oneapi/script_generator_oneapi.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/oneapi/script_multi_generator_oneapi.py b/examples/oneapi/script_multi_generator_oneapi.py deleted file mode 100644 index 42328744..00000000 --- a/examples/oneapi/script_multi_generator_oneapi.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/oneapi/search_graph_oneapi.py b/examples/oneapi/search_graph_oneapi.py deleted file mode 100644 index b25cbfa6..00000000 --- a/examples/oneapi/search_graph_oneapi.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -Example of Search Graph -""" -from scrapegraphai.graphs import SearchGraph - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/oneapi/search_graph_schema_oneapi.py b/examples/oneapi/search_graph_schema_oneapi.py deleted file mode 100644 index 7fc44539..00000000 --- a/examples/oneapi/search_graph_schema_oneapi.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Example of Search Graph -""" -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -from pydantic import BaseModel, Field -from typing import List - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/oneapi/smart_scraper_lite_oneapi.py b/examples/oneapi/smart_scraper_lite_oneapi.py deleted file mode 100644 index b271acb3..00000000 --- a/examples/oneapi/smart_scraper_lite_oneapi.py +++ /dev/null @@ -1,32 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -graph_config = { - "llm": { - "api_key": os.getenv("ONEAPI_API_KEY"), - "model": "oneapi/gpt-3.5-turbo", - "base_url": "http://127.0.0.1:3000/v1", - }, - "verbose": True, - "headless": False, -} - -smart_scraper_lite_graph = SmartScraperLiteGraph( - prompt="Who is Marco Perini?", - source="https://perinim.github.io/", - config=graph_config -) - -result = smart_scraper_lite_graph.run() -print(json.dumps(result, indent=4)) - -graph_exec_info = smart_scraper_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/oneapi/smart_scraper_multi_concat_oneapi.py b/examples/oneapi/smart_scraper_multi_concat_oneapi.py deleted file mode 100644 index bbadbcfd..00000000 --- a/examples/oneapi/smart_scraper_multi_concat_oneapi.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import json -from scrapegraphai.graphs import SmartScraperMultiConcatGraph - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiConcatGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/oneapi/smart_scraper_multi_lite_oneapi.py b/examples/oneapi/smart_scraper_multi_lite_oneapi.py deleted file mode 100644 index 8cf66dea..00000000 --- a/examples/oneapi/smart_scraper_multi_lite_oneapi.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/oneapi/smart_scraper_multi_oneapi.py b/examples/oneapi/smart_scraper_multi_oneapi.py deleted file mode 100644 index 37b7b6e8..00000000 --- a/examples/oneapi/smart_scraper_multi_oneapi.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" - -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/oneapi/smart_scraper_oneapi.py b/examples/oneapi/smart_scraper_oneapi.py deleted file mode 100644 index 30b12aa3..00000000 --- a/examples/oneapi/smart_scraper_oneapi.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the titles", - # also accepts a string with the already downloaded HTML code - source="https://www.wired.com/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/oneapi/smart_scraper_schema_oneapi.py b/examples/oneapi/smart_scraper_schema_oneapi.py deleted file mode 100644 index 0c011bb6..00000000 --- a/examples/oneapi/smart_scraper_schema_oneapi.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper and OneAPI -""" -from typing import List -from pydantic import BaseModel, Field -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ********************************************* - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config, - schema=Projects -) - -# ************************************************ -# Get graph execution info -# ************************************************ -result = smart_scraper_graph.run() -print(result) -print(prettify_exec_info(result)) diff --git a/examples/oneapi/smartscraper_oneapi.py b/examples/oneapi/smartscraper_oneapi.py deleted file mode 100644 index f0783782..00000000 --- a/examples/oneapi/smartscraper_oneapi.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ********************************************* - -graph_config = { - "llm": { - "api_key": "***************************", - "model": "oneapi/qwen-turbo", - "base_url": "http://127.0.0.1:3000/v1", # 设置 OneAPI URL - } -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="该网站为XXXXX,请提取出标题、发布时间、发布来源以及内容摘要,并以中文回答。", - # 也可以使用已下载的 HTML 代码的字符串 - source="http://XXXX", - config=graph_config -) - -# ************************************************ -# Get graph execution info -# ************************************************ -result = smart_scraper_graph.run() -print(result) -print(prettify_exec_info(result)) diff --git a/examples/oneapi/xml_scraper_graph_multi_oneapi.py b/examples/oneapi/xml_scraper_graph_multi_oneapi.py deleted file mode 100644 index b459fdd3..00000000 --- a/examples/oneapi/xml_scraper_graph_multi_oneapi.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "openai/gpt-3.5-turbo", - }, -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/oneapi/xml_scraper_oneapi.py b/examples/oneapi/xml_scraper_oneapi.py deleted file mode 100644 index 7ea7fad5..00000000 --- a/examples/oneapi/xml_scraper_oneapi.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("ONEAPI_KEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "openai/gpt-3.5-turbo", - }, - "verbose":False, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/openai/.env.example b/examples/openai/.env.example deleted file mode 100644 index afa13602..00000000 --- a/examples/openai/.env.example +++ /dev/null @@ -1 +0,0 @@ -OPENAI_API_KEY="YOUR OPENAI API KEY" \ No newline at end of file diff --git a/examples/openai/inputs/books.xml b/examples/openai/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/openai/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/openai/inputs/example.json b/examples/openai/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/openai/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/openai/inputs/markdown_example.md b/examples/openai/inputs/markdown_example.md deleted file mode 100644 index 85088f29..00000000 --- a/examples/openai/inputs/markdown_example.md +++ /dev/null @@ -1,35 +0,0 @@ -Marco Perini Toggle navigation - - * About - * Projects(current) - -Projects - -Competitions - - * CV - * ____ - -# Projects - - ![project thumbnail Rotary Pendulum RL -Open Source project aimed at controlling a real life rotary pendulum using RL -algorithms ](/projects/rotary-pendulum-rl/) - - ![project thumbnail DQN -Implementation from scratch Developed a Deep Q-Network algorithm to train a -simple and double pendulum ](https://github.com/PeriniM/DQN-SwingUp) - - ![project thumbnail Multi Agents HAED -University project which focuses on simulating a multi-agent system to perform -environment mapping. Agents, equipped with sensors, explore and record their -surroundings, considering uncertainties in their readings. -](https://github.com/PeriniM/Multi-Agents-HAED) - - ![project thumbnail Wireless ESC for Modular -Drones Modular drone architecture proposal and proof of concept. The project -received maximum grade. ](/projects/wireless-esc-drone/) - -© Copyright 2023 Marco Perini. Powered by Jekyll with -al-folio theme. Hosted by [GitHub -Pages](https://pages.github.com/). \ No newline at end of file diff --git a/examples/openai/inputs/plain_html_example.txt b/examples/openai/inputs/plain_html_example.txt deleted file mode 100644 index 78f814ae..00000000 --- a/examples/openai/inputs/plain_html_example.txt +++ /dev/null @@ -1,105 +0,0 @@ - -
- - -
-
-
- - -
- \ No newline at end of file diff --git a/examples/openai/inputs/username.csv b/examples/openai/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/openai/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/openai/rate_limit_openai.py b/examples/openai/rate_limit_openai.py deleted file mode 100644 index 9455e798..00000000 --- a/examples/openai/rate_limit_openai.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" - -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "api_key": os.getenv("OPENAI_API_KEY"), - "model": "openai/gpt-4o", - "rate_limit": { - "requests_per_second": 1 - } - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me what does the company do, the name and a contact email.", - source="https://scrapegraphai.com/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/openai/readme.md b/examples/openai/readme.md deleted file mode 100644 index 9a517ac6..00000000 --- a/examples/openai/readme.md +++ /dev/null @@ -1 +0,0 @@ -This folder contains an example of how to use ScrapeGraph-AI with OpenAI, an artificial intelligence platform. The examples show how to extract information from a website using a natural language prompt. \ No newline at end of file diff --git a/examples/openai/scrape_plain_text_openai.py b/examples/openai/scrape_plain_text_openai.py deleted file mode 100644 index 27a65663..00000000 --- a/examples/openai/scrape_plain_text_openai.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "openai/gpt-4o", - }, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/openai/screenshot_scraper.py b/examples/openai/screenshot_scraper.py deleted file mode 100644 index f5576b64..00000000 --- a/examples/openai/screenshot_scraper.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import ScreenshotScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "api_key": os.getenv("OPENAI_API_KEY"), - "model": "openai/gpt-4o", - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the ScreenshotScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = ScreenshotScraperGraph( - prompt="List me all the projects", - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/readme.md b/examples/readme.md index 3d3501fb..b750ccf8 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -1,41 +1,66 @@ -# Benchmark analysis -# Local models -The two websites benchmark are: -- Example 1: https://perinim.github.io/projects -- Example 2: https://www.wired.com (at 17/4/2024) +# 🕷️ Scrapegraph-ai Examples -Both are strored locally as txt file in .txt format because in this way we do not have to think about the internet connection +This directory contains various example implementations of Scrapegraph-ai for different use cases. Each example demonstrates how to leverage the power of Scrapegraph-ai for specific scenarios. -The time is measured in seconds +> **Note:** While these examples showcase implementations using OpenAI and Ollama, Scrapegraph-ai supports many other LLM providers! Check out our [documentation](https://docs-oss.scrapegraphai.com/examples) for the full list of supported providers. -The model runned for this benchmark is Mistral on Ollama with nomic-embed-text +## 📚 Available Examples -| Hardware | Example 1 | Example 2 | -| ----------------------- | --------- | --------- | -| Macbook pro 14' m1 | 11.60s | 26.61s | -| Macbook pro 16' m2 max | 8.05s | 12.17s | +- 🧠 `smart_scraper/` - Advanced web scraping with intelligent content extraction +- 🔎 `search_graph/` - Web search and data retrieval +- ⚙️ `script_generator_graph/` - Automated script generation +- 🌐 `depth_search_graph/` - Deep web crawling and content exploration +- 📊 `csv_scraper_graph/` - Scraping and processing data into CSV format +- 📑 `xml_scraper_graph/` - XML data extraction and processing +- 🎤 `speech_graph/` - Speech processing and analysis +- 🔄 `omni_scraper_graph/` - Universal web scraping for multiple data types +- 🔍 `omni_search_graph/` - Comprehensive search across multiple sources +- 📄 `document_scraper_graph/` - Document parsing and data extraction +- 🛠️ `custom_graph/` - Custom graph implementation examples +- 💻 `code_generator_graph/` - Code generation utilities +- 📋 `json_scraper_graph/` - JSON data extraction and processing +- 📋 `colab example`: + + Open In Colab + -**Note**: the examples on Docker are not runned on other devices than the Macbook because the performance are to slow (10 times slower than Ollama). Indeed the results are the following: +## 🚀 Getting Started -| Hardware | Example 1 | Example 2 | -| ------------------ | --------- | --------- | -| Macbook 14' m1 pro | 139.89 | Too long | -# Performance on APIs services -### Example 1: personal portfolio -**URL**: https://perinim.github.io/projects -**Task**: List me all the projects with their description. +1. Choose the example that best fits your use case +2. Navigate to the corresponding directory +3. Follow the README instructions in each directory +4. Configure any required environment variables using the provided `.env.example` files -| Name | Execution time (seconds) | total_tokens | prompt_tokens | completion_tokens | successful_requests | total_cost_USD | -| ------------------- | ------------------------ | ------------ | ------------- | ----------------- | ------------------- | -------------- | -| gpt-3.5-turbo | 25.22 | 445 | 272 | 173 | 1 | 0.000754 | -| gpt-4-turbo-preview | 9.53 | 449 | 272 | 177 | 1 | 0.00803 | +## ⚡ Quick Setup -### Example 2: Wired -**URL**: https://www.wired.com -**Task**: List me all the articles with their description. +```bash +pip install scrapegraphai -| Name | Execution time (seconds) | total_tokens | prompt_tokens | completion_tokens | successful_requests | total_cost_USD | -| ------------------- | ------------------------ | ------------ | ------------- | ----------------- | ------------------- | -------------- | -| gpt-3.5-turbo | 25.89 | 445 | 272 | 173 | 1 | 0.000754 | -| gpt-4-turbo-preview | 64.70 | 3573 | 2199 | 1374 | 1 | 0.06321 | +playwright install +# choose an example +cd examples/smart_scraper_graph/openai + +# run the example +python smart_scraper_openai.py +``` + +## 📋 Requirements + +Each example may have its own specific requirements. Please refer to the individual README files in each directory for detailed setup instructions. + +## 📚 Additional Resources + +- 📖 [Full Documentation](https://docs-oss.scrapegraphai.com/examples) +- 💡 [Examples Repository](https://github.com/ScrapeGraphAI/ScrapegraphLib-Examples) +- 🤝 [Community Support](https://github.com/ScrapeGraphAI/scrapegraph-ai/discussions) + +## 🤔 Need Help? + +- Check out our [documentation](https://docs-oss.scrapegraphai.com) +- Join our [Discord community](https://discord.gg/scrapegraphai) +- Open an [issue](https://github.com/ScrapeGraphAI/scrapegraph-ai/issues) + +--- + +⭐ Don't forget to star our repository if you find these examples helpful! diff --git a/examples/scrapegraph-api/smart_scraper_api.py b/examples/scrapegraph-api/smart_scraper_api.py deleted file mode 100644 index 8a292ee9..00000000 --- a/examples/scrapegraph-api/smart_scraper_api.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -graph_config = { - "llm": { - "model": "scrapegraphai/smart-scraper", - "api_key": os.getenv("SCRAPEGRAPH_API_KEY") - }, - "verbose": True, - "headless": False, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="Extract me all the articles", - source="https://www.wired.com", - config=graph_config -) - -result = smart_scraper_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/script_generator_graph/.env.example b/examples/script_generator_graph/.env.example new file mode 100644 index 00000000..216ab8a7 --- /dev/null +++ b/examples/script_generator_graph/.env.example @@ -0,0 +1,13 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# Script Generator Settings +DEFAULT_LANGUAGE=python +INCLUDE_COMMENTS=true +ADD_TYPE_HINTS=true +CODE_STYLE=pep8 \ No newline at end of file diff --git a/examples/script_generator_graph/README.md b/examples/script_generator_graph/README.md new file mode 100644 index 00000000..7d1495c6 --- /dev/null +++ b/examples/script_generator_graph/README.md @@ -0,0 +1,30 @@ +# Script Generator Graph Example + +This example demonstrates how to use Scrapegraph-ai to generate automation scripts based on data analysis. + +## Features + +- Automated script generation +- Task automation +- Code optimization +- Multiple language support + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import ScriptGeneratorGraph + +graph = ScriptGeneratorGraph() +script = graph.generate("task description") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/local_models/script_generator_ollama.py b/examples/script_generator_graph/ollama/script_generator_ollama.py similarity index 100% rename from examples/local_models/script_generator_ollama.py rename to examples/script_generator_graph/ollama/script_generator_ollama.py diff --git a/examples/local_models/script_multi_generator_ollama.py b/examples/script_generator_graph/ollama/script_multi_generator_ollama.py similarity index 100% rename from examples/local_models/script_multi_generator_ollama.py rename to examples/script_generator_graph/ollama/script_multi_generator_ollama.py diff --git a/examples/openai/script_multi_generator_openai.py b/examples/script_generator_graph/openai/script_generator_multi_openai.py similarity index 100% rename from examples/openai/script_multi_generator_openai.py rename to examples/script_generator_graph/openai/script_generator_multi_openai.py diff --git a/examples/openai/script_generator_openai.py b/examples/script_generator_graph/openai/script_generator_openai.py similarity index 100% rename from examples/openai/script_generator_openai.py rename to examples/script_generator_graph/openai/script_generator_openai.py diff --git a/examples/openai/script_generator_schema_openai.py b/examples/script_generator_graph/openai/script_generator_schema_openai.py similarity index 100% rename from examples/openai/script_generator_schema_openai.py rename to examples/script_generator_graph/openai/script_generator_schema_openai.py diff --git a/examples/search_graph/.env.example b/examples/search_graph/.env.example new file mode 100644 index 00000000..a4b25c88 --- /dev/null +++ b/examples/search_graph/.env.example @@ -0,0 +1,11 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Search API Configuration +SERP_API_KEY=your-serp-api-key-here + +# Optional Configurations +MAX_SEARCH_RESULTS=10 +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 \ No newline at end of file diff --git a/examples/search_graph/README.md b/examples/search_graph/README.md new file mode 100644 index 00000000..084c6ea2 --- /dev/null +++ b/examples/search_graph/README.md @@ -0,0 +1,31 @@ +# Search Graph Example + +This example shows how to implement a search graph for web content retrieval and analysis using Scrapegraph-ai. + +## Features + +- Web search integration +- Content relevance scoring +- Result filtering +- Data aggregation + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import SearchGraph + +graph = SearchGraph() +results = graph.search("your search query") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key +- `SERP_API_KEY`: Your SERP API key (optional) \ No newline at end of file diff --git a/examples/local_models/search_graph_ollama.py b/examples/search_graph/ollama/search_graph_ollama.py similarity index 100% rename from examples/local_models/search_graph_ollama.py rename to examples/search_graph/ollama/search_graph_ollama.py diff --git a/examples/local_models/search_graph_schema_ollama.py b/examples/search_graph/ollama/search_graph_schema_ollama.py similarity index 100% rename from examples/local_models/search_graph_schema_ollama.py rename to examples/search_graph/ollama/search_graph_schema_ollama.py diff --git a/examples/openai/search_graph_openai.py b/examples/search_graph/openai/search_graph_openai.py similarity index 100% rename from examples/openai/search_graph_openai.py rename to examples/search_graph/openai/search_graph_openai.py diff --git a/examples/openai/search_graph_schema_openai.py b/examples/search_graph/openai/search_graph_schema_openai.py similarity index 100% rename from examples/openai/search_graph_schema_openai.py rename to examples/search_graph/openai/search_graph_schema_openai.py diff --git a/examples/openai/search_link_graph_openai.py b/examples/search_graph/openai/search_link_graph_openai.py similarity index 100% rename from examples/openai/search_link_graph_openai.py rename to examples/search_graph/openai/search_link_graph_openai.py diff --git a/examples/single_node/fetch_node.py b/examples/single_node/fetch_node.py deleted file mode 100644 index ed2de2e0..00000000 --- a/examples/single_node/fetch_node.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Example of custom graph using existing nodes -""" - -from scrapegraphai.nodes import FetchNode - -# ************************************************ -# Define the node -# ************************************************ - - -fetch_node = FetchNode( - input="url | local_dir", - output=["doc"], - node_config={ - "headless": False - } -) - -# ************************************************ -# Test the node -# ************************************************ - -state = { - "url": "https://twitter.com/home" -} - -result = fetch_node.execute(state) - -print(result) diff --git a/examples/single_node/image2text_node.py b/examples/single_node/image2text_node.py deleted file mode 100644 index 0f691e8a..00000000 --- a/examples/single_node/image2text_node.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Example of ImageToTextNode -""" - -import os -from dotenv import load_dotenv -from scrapegraphai.nodes import ImageToTextNode -from scrapegraphai.models import OpenAIImageToText - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "gpt-4o", - "temperature": 0, - }, -} - -# ************************************************ -# Define the node -# ************************************************ - -llm_model = OpenAIImageToText(graph_config["llm"]) - -image_to_text_node = ImageToTextNode( - input="img_url", - output=["img_desc"], - node_config={ - "llm_model": llm_model, - "headless": False - } -) - -# ************************************************ -# Test the node -# ************************************************ - -state = { - "img_url": [ - "https://perinim.github.io/assets/img/rotary_pybullet.jpg", - "https://perinim.github.io/assets/img/value-policy-heatmaps.jpg", - ], -} - -result = image_to_text_node.execute(state) - -print(result) diff --git a/examples/single_node/kg_node.py b/examples/single_node/kg_node.py deleted file mode 100644 index 37d1d9a4..00000000 --- a/examples/single_node/kg_node.py +++ /dev/null @@ -1,79 +0,0 @@ -""" -Example of knowledge graph node -""" - -import os -from langchain_openai import ChatOpenAI -from scrapegraphai.nodes import KnowledgeGraphNode - -job_postings = { - "Job Postings": { - "Company A": [ - { - "title": "Software Engineer", - "description": "Develop and maintain software applications.", - "location": "New York, NY", - "date_posted": "2024-05-01", - "requirements": ["Python", "Django", "REST APIs"] - }, - { - "title": "Data Scientist", - "description": "Analyze and interpret complex data.", - "location": "San Francisco, CA", - "date_posted": "2024-05-05", - "requirements": ["Python", "Machine Learning", "SQL"] - } - ], - "Company B": [ - { - "title": "Project Manager", - "description": "Manage software development projects.", - "location": "Boston, MA", - "date_posted": "2024-04-20", - "requirements": ["Project Management", "Agile", "Scrum"] - } - ] - } -} - - - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -openai_key = os.getenv("OPENAI_APIKEY") - -graph_config = { - "llm": { - "api_key": openai_key, - "model": "gpt-4o", - "temperature": 0, - }, - "verbose": True, -} - -# ************************************************ -# Define the node -# ************************************************ - -llm_model = ChatOpenAI(graph_config["llm"]) - -robots_node = KnowledgeGraphNode( - input="user_prompt & answer_dict", - output=["is_scrapable"], - node_config={"llm_model": llm_model} -) - -# ************************************************ -# Test the node -# ************************************************ - -state = { - "user_prompt": "What are the job postings?", - "answer_dict": job_postings -} - -result = robots_node.execute(state) - -print(result) diff --git a/examples/single_node/robot_node.py b/examples/single_node/robot_node.py deleted file mode 100644 index dcb70e3d..00000000 --- a/examples/single_node/robot_node.py +++ /dev/null @@ -1,49 +0,0 @@ -""" -Example of custom graph using existing nodes -""" - -from langchain_community.chat_models import ChatOllama -from scrapegraphai.nodes import RobotsNode - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "llama3", - "temperature": 0, - "streaming": True - }, - "embeddings": { - "model": "nomic-embed-text", - "temperature": 0, - # "base_url": "http://localhost:11434", # set ollama URL arbitrarily - } -} - -# ************************************************ -# Define the node -# ************************************************ - -llm_model = ChatOllama(graph_config["llm"]) - -robots_node = RobotsNode( - input="url", - output=["is_scrapable"], - node_config={"llm_model": llm_model, - "headless": False - } -) - -# ************************************************ -# Test the node -# ************************************************ - -state = { - "url": "https://twitter.com/home" -} - -result = robots_node.execute(state) - -print(result) diff --git a/examples/single_node/search_internet_node.py b/examples/single_node/search_internet_node.py deleted file mode 100644 index c998cdd1..00000000 --- a/examples/single_node/search_internet_node.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Example of custom graph using existing nodes -""" - -from langchain_community.chat_models import ChatOllama -from scrapegraphai.nodes import SearchInternetNode - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "llama3", - "temperature": 0, - "streaming": True - }, - "search_engine": "google", - "max_results": 3, - "verbose": True -} - -# ************************************************ -# Define the node -# ************************************************ - -llm_model = ChatOllama(graph_config["llm"]) - -search_node = SearchInternetNode( - input="user_input", - output=["search_results"], - node_config={ - "llm_model": llm_model, - "search_engine": graph_config["search_engine"], - "max_results": graph_config["max_results"], - "verbose": graph_config["verbose"] - } -) - -# ************************************************ -# Test the node -# ************************************************ - -state = { - "user_input": "What is the capital of France?" -} - -result = search_node.execute(state) - -print(result) diff --git a/examples/smart_scraper_graph/.env.example b/examples/smart_scraper_graph/.env.example new file mode 100644 index 00000000..0c8d0b86 --- /dev/null +++ b/examples/smart_scraper_graph/.env.example @@ -0,0 +1,7 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 diff --git a/examples/smart_scraper_graph/README.md b/examples/smart_scraper_graph/README.md new file mode 100644 index 00000000..d5f0d564 --- /dev/null +++ b/examples/smart_scraper_graph/README.md @@ -0,0 +1,30 @@ +# Smart Scraper Example + +This example demonstrates how to use Scrapegraph-ai for intelligent web scraping with automatic content detection and extraction. + +## Features + +- Intelligent content detection +- Automatic data extraction +- Content classification +- Clean data output + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your OpenAI API key in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import SmartScraperGraph + +graph = SmartScraperGraph() +results = graph.scrape("https://example.com") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key diff --git a/examples/local_models/smart_scraper_lite_ollama.py b/examples/smart_scraper_graph/ollama/smart_scraper_lite_ollama.py similarity index 89% rename from examples/local_models/smart_scraper_lite_ollama.py rename to examples/smart_scraper_graph/ollama/smart_scraper_lite_ollama.py index 2cf6c402..9c4b9a69 100644 --- a/examples/local_models/smart_scraper_lite_ollama.py +++ b/examples/smart_scraper_graph/ollama/smart_scraper_lite_ollama.py @@ -1,8 +1,10 @@ -""" +""" Basic example of scraping pipeline using SmartScraper """ + import json + from scrapegraphai.graphs import SmartScraperLiteGraph from scrapegraphai.utils import prettify_exec_info @@ -10,17 +12,16 @@ "llm": { "model": "ollama/llama3.1", "temperature": 0, - "format": "json", "base_url": "http://localhost:11434", }, "verbose": True, - "headless": False + "headless": False, } smart_scraper_lite_graph = SmartScraperLiteGraph( prompt="Who is Marco Perini?", source="https://perinim.github.io/", - config=graph_config + config=graph_config, ) result = smart_scraper_lite_graph.run() diff --git a/examples/mistral/smart_scraper_multi_concat_mistral.py b/examples/smart_scraper_graph/ollama/smart_scraper_multi_concat_ollama.py similarity index 75% rename from examples/mistral/smart_scraper_multi_concat_mistral.py rename to examples/smart_scraper_graph/ollama/smart_scraper_multi_concat_ollama.py index 9cef8a16..a29ac3fc 100644 --- a/examples/mistral/smart_scraper_multi_concat_mistral.py +++ b/examples/smart_scraper_graph/ollama/smart_scraper_multi_concat_ollama.py @@ -1,9 +1,11 @@ -""" +""" Basic example of scraping pipeline using SmartScraper """ -import os + import json + from dotenv import load_dotenv + from scrapegraphai.graphs import SmartScraperMultiConcatGraph load_dotenv() @@ -11,10 +13,12 @@ # ************************************************ # Define the configuration for the graph # ************************************************ + graph_config = { "llm": { - "api_key": os.getenv("MISTRAL_API_KEY"), - "model": "mistralai/open-mistral-nemo", + "model": "ollama/llama3.1", + "temperature": 0, + "base_url": "http://localhost:11434", # set ollama URL arbitrarily }, "verbose": True, "headless": False, @@ -26,12 +30,9 @@ multiple_search_graph = SmartScraperMultiConcatGraph( prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], + source=["https://perinim.github.io/", "https://perinim.github.io/cv/"], schema=None, - config=graph_config + config=graph_config, ) result = multiple_search_graph.run() diff --git a/examples/local_models/smart_scraper_multi_lite_ollama.py b/examples/smart_scraper_graph/ollama/smart_scraper_multi_lite_ollama.py similarity index 82% rename from examples/local_models/smart_scraper_multi_lite_ollama.py rename to examples/smart_scraper_graph/ollama/smart_scraper_multi_lite_ollama.py index f09c4cb4..15055f96 100644 --- a/examples/local_models/smart_scraper_multi_lite_ollama.py +++ b/examples/smart_scraper_graph/ollama/smart_scraper_multi_lite_ollama.py @@ -1,7 +1,9 @@ -""" +""" Basic example of scraping pipeline using SmartScraper """ + import json + from scrapegraphai.graphs import SmartScraperMultiLiteGraph from scrapegraphai.utils import prettify_exec_info @@ -13,11 +15,10 @@ "llm": { "model": "ollama/llama3.1", "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly "base_url": "http://localhost:11434", # set ollama URL arbitrarily }, "verbose": True, - "headless": False + "headless": False, } # ************************************************ @@ -26,11 +27,8 @@ smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config + source=["https://perinim.github.io/", "https://perinim.github.io/cv/"], + config=graph_config, ) result = smart_scraper_multi_lite_graph.run() @@ -42,4 +40,3 @@ graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/local_models/smart_scraper_multi_ollama.py b/examples/smart_scraper_graph/ollama/smart_scraper_multi_ollama.py similarity index 77% rename from examples/local_models/smart_scraper_multi_ollama.py rename to examples/smart_scraper_graph/ollama/smart_scraper_multi_ollama.py index c9d49793..04eb0e67 100644 --- a/examples/local_models/smart_scraper_multi_ollama.py +++ b/examples/smart_scraper_graph/ollama/smart_scraper_multi_ollama.py @@ -1,8 +1,9 @@ -""" +""" Basic example of scraping pipeline using SmartScraper """ import json + from scrapegraphai.graphs import SmartScraperMultiGraph # ************************************************ @@ -12,12 +13,10 @@ "llm": { "model": "ollama/llama3.1", "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly # "base_url": "http://localhost:11434", # set ollama URL arbitrarily }, - "verbose": True, - "headless": False + "headless": False, } @@ -27,12 +26,9 @@ multiple_search_graph = SmartScraperMultiGraph( prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], + source=["https://perinim.github.io/", "https://perinim.github.io/cv/"], schema=None, - config=graph_config + config=graph_config, ) result = multiple_search_graph.run() diff --git a/examples/local_models/smart_scraper_ollama.py b/examples/smart_scraper_graph/ollama/smart_scraper_ollama.py similarity index 93% rename from examples/local_models/smart_scraper_ollama.py rename to examples/smart_scraper_graph/ollama/smart_scraper_ollama.py index b08dceb9..9642b3f8 100644 --- a/examples/local_models/smart_scraper_ollama.py +++ b/examples/smart_scraper_graph/ollama/smart_scraper_ollama.py @@ -13,7 +13,6 @@ "llm": { "model": "ollama/llama3.2:3b", "temperature": 0, - "format": "json", # Ollama needs the format to be specified explicitly # "base_url": "http://localhost:11434", # set ollama URL arbitrarily "model_tokens": 4096, }, diff --git a/examples/local_models/smart_scraper_schema_ollama.py b/examples/smart_scraper_graph/ollama/smart_scraper_schema_ollama.py similarity index 100% rename from examples/local_models/smart_scraper_schema_ollama.py rename to examples/smart_scraper_graph/ollama/smart_scraper_schema_ollama.py diff --git a/examples/openai/smart_scraper_lite_openai.py b/examples/smart_scraper_graph/openai/smart_scraper_lite_openai.py similarity index 95% rename from examples/openai/smart_scraper_lite_openai.py rename to examples/smart_scraper_graph/openai/smart_scraper_lite_openai.py index 5de725bb..3d768548 100644 --- a/examples/openai/smart_scraper_lite_openai.py +++ b/examples/smart_scraper_graph/openai/smart_scraper_lite_openai.py @@ -1,9 +1,12 @@ -""" +""" Basic example of scraping pipeline using SmartScraper """ -import os + import json +import os + from dotenv import load_dotenv + from scrapegraphai.graphs import SmartScraperLiteGraph from scrapegraphai.utils import prettify_exec_info @@ -21,7 +24,7 @@ smart_scraper_lite_graph = SmartScraperLiteGraph( prompt="Who is Marco Perini?", source="https://perinim.github.io/", - config=graph_config + config=graph_config, ) result = smart_scraper_lite_graph.run() @@ -29,4 +32,3 @@ graph_exec_info = smart_scraper_lite_graph.get_execution_info() print(prettify_exec_info(graph_exec_info)) - diff --git a/examples/openai/smart_scraper_multi_concat_openai.py b/examples/smart_scraper_graph/openai/smart_scraper_multi_concat_openai.py similarity index 86% rename from examples/openai/smart_scraper_multi_concat_openai.py rename to examples/smart_scraper_graph/openai/smart_scraper_multi_concat_openai.py index 650971f1..4774e620 100644 --- a/examples/openai/smart_scraper_multi_concat_openai.py +++ b/examples/smart_scraper_graph/openai/smart_scraper_multi_concat_openai.py @@ -1,9 +1,12 @@ -""" +""" Basic example of scraping pipeline using SmartScraper """ -import os + import json +import os + from dotenv import load_dotenv + from scrapegraphai.graphs import SmartScraperMultiConcatGraph load_dotenv() @@ -28,12 +31,9 @@ multiple_search_graph = SmartScraperMultiConcatGraph( prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], + source=["https://perinim.github.io/", "https://perinim.github.io/cv/"], schema=None, - config=graph_config + config=graph_config, ) result = multiple_search_graph.run() diff --git a/examples/openai/smart_scraper_multi_lite_openai.py b/examples/smart_scraper_graph/openai/smart_scraper_multi_lite_openai.py similarity index 89% rename from examples/openai/smart_scraper_multi_lite_openai.py rename to examples/smart_scraper_graph/openai/smart_scraper_multi_lite_openai.py index 69eeafc7..acc970be 100644 --- a/examples/openai/smart_scraper_multi_lite_openai.py +++ b/examples/smart_scraper_graph/openai/smart_scraper_multi_lite_openai.py @@ -1,9 +1,12 @@ -""" +""" Basic example of scraping pipeline using SmartScraper """ -import os + import json +import os + from dotenv import load_dotenv + from scrapegraphai.graphs import SmartScraperMultiLiteGraph from scrapegraphai.utils import prettify_exec_info @@ -29,11 +32,8 @@ smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config + source=["https://perinim.github.io/", "https://perinim.github.io/cv/"], + config=graph_config, ) result = smart_scraper_multi_lite_graph.run() diff --git a/examples/openai/smart_scraper_multi_openai.py b/examples/smart_scraper_graph/openai/smart_scraper_multi_openai.py similarity index 86% rename from examples/openai/smart_scraper_multi_openai.py rename to examples/smart_scraper_graph/openai/smart_scraper_multi_openai.py index ba889c96..ec510fc2 100644 --- a/examples/openai/smart_scraper_multi_openai.py +++ b/examples/smart_scraper_graph/openai/smart_scraper_multi_openai.py @@ -1,9 +1,12 @@ -""" +""" Basic example of scraping pipeline using SmartScraper """ -import os + import json +import os + from dotenv import load_dotenv + from scrapegraphai.graphs import SmartScraperMultiGraph load_dotenv() @@ -29,12 +32,9 @@ multiple_search_graph = SmartScraperMultiGraph( prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], + source=["https://perinim.github.io/", "https://perinim.github.io/cv/"], schema=None, - config=graph_config + config=graph_config, ) result = multiple_search_graph.run() diff --git a/examples/openai/smart_scraper_openai.py b/examples/smart_scraper_graph/openai/smart_scraper_openai.py similarity index 100% rename from examples/openai/smart_scraper_openai.py rename to examples/smart_scraper_graph/openai/smart_scraper_openai.py diff --git a/examples/openai/smart_scraper_schema_openai.py b/examples/smart_scraper_graph/openai/smart_scraper_schema_openai.py similarity index 97% rename from examples/openai/smart_scraper_schema_openai.py rename to examples/smart_scraper_graph/openai/smart_scraper_schema_openai.py index 32e8891a..3a75bd5a 100644 --- a/examples/openai/smart_scraper_schema_openai.py +++ b/examples/smart_scraper_graph/openai/smart_scraper_schema_openai.py @@ -1,10 +1,13 @@ -""" +""" Basic example of scraping pipeline using SmartScraper with schema """ + import os from typing import List + from dotenv import load_dotenv from pydantic import BaseModel, Field + from scrapegraphai.graphs import SmartScraperGraph load_dotenv() @@ -13,13 +16,16 @@ # Define the output schema for the graph # ************************************************ + class Project(BaseModel): title: str = Field(description="The title of the project") description: str = Field(description="The description of the project") + class Projects(BaseModel): projects: List[Project] + # ************************************************ # Define the configuration for the graph # ************************************************ @@ -43,7 +49,7 @@ class Projects(BaseModel): prompt="List me all the projects with their description", source="https://perinim.github.io/projects/", schema=Projects, - config=graph_config + config=graph_config, ) result = smart_scraper_graph.run() diff --git a/examples/speech_graph/.env.example b/examples/speech_graph/.env.example new file mode 100644 index 00000000..93aa505d --- /dev/null +++ b/examples/speech_graph/.env.example @@ -0,0 +1,14 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Whisper API Configuration (Optional) +WHISPER_API_KEY=your-whisper-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# Speech Settings +AUDIO_FORMAT=mp3 +SAMPLE_RATE=16000 \ No newline at end of file diff --git a/examples/speech_graph/README.md b/examples/speech_graph/README.md new file mode 100644 index 00000000..35be155f --- /dev/null +++ b/examples/speech_graph/README.md @@ -0,0 +1,31 @@ +# Speech Graph Example + +This example demonstrates how to use Scrapegraph-ai for speech processing and analysis. + +## Features + +- Speech-to-text conversion +- Audio processing +- Text analysis +- Sentiment analysis + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import SpeechGraph + +graph = SpeechGraph() +text = graph.process("audio_file.mp3") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key +- `WHISPER_API_KEY`: Your Whisper API key (optional) \ No newline at end of file diff --git a/examples/openai/speech_graph_openai.py b/examples/speech_graph/speech_graph_openai.py similarity index 100% rename from examples/openai/speech_graph_openai.py rename to examples/speech_graph/speech_graph_openai.py diff --git a/examples/together/.env.example b/examples/together/.env.example deleted file mode 100644 index 7004713a..00000000 --- a/examples/together/.env.example +++ /dev/null @@ -1 +0,0 @@ -TOGETHER_APIKEY="your api key" \ No newline at end of file diff --git a/examples/together/code_generator_graph_togehter.py b/examples/together/code_generator_graph_togehter.py deleted file mode 100644 index aefbeba4..00000000 --- a/examples/together/code_generator_graph_togehter.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Basic example of scraping pipeline using Code Generator with schema -""" - -import os, json -from typing import List -from dotenv import load_dotenv -from pydantic import BaseModel, Field -from scrapegraphai.graphs import CodeGeneratorGraph - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_KEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, - "headless": False, - "reduction": 2, - "max_iterations": { - "overall": 10, - "syntax": 3, - "execution": 3, - "validation": 3, - "semantic": 3 - }, - "output_file_name": "extracted_data.py" -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -code_generator_graph = CodeGeneratorGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = code_generator_graph.run() -print(result) diff --git a/examples/together/csv_scraper_graph_multi_together.py b/examples/together/csv_scraper_graph_multi_together.py deleted file mode 100644 index beee56c1..00000000 --- a/examples/together/csv_scraper_graph_multi_together.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperMultiGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} -# ************************************************ -# Create the CSVScraperMultiGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperMultiGraph( - prompt="List me all the last names", - source=[str(text), str(text)], - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/together/csv_scraper_together.py b/examples/together/csv_scraper_together.py deleted file mode 100644 index 5d1a3474..00000000 --- a/examples/together/csv_scraper_together.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using CSVScraperGraph from CSV documents -""" -import os -from dotenv import load_dotenv -import pandas as pd -from scrapegraphai.graphs import CSVScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the CSV file -# ************************************************ - -FILE_NAME = "inputs/username.csv" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -text = pd.read_csv(file_path) - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} -# ************************************************ -# Create the CSVScraperGraph instance and run it -# ************************************************ - -csv_scraper_graph = CSVScraperGraph( - prompt="List me all the last names", - source=str(text), # Pass the content of the file, not the file object - config=graph_config -) - -result = csv_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = csv_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/together/depth_search_graph_together.py b/examples/together/depth_search_graph_together.py deleted file mode 100644 index fb7b4d9e..00000000 --- a/examples/together/depth_search_graph_together.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -depth_search_graph_opeani example -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import DepthSearchGraph - -load_dotenv() - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, - "headless": False, - "depth": 2, - "only_inside_links": False, -} - -search_graph = DepthSearchGraph( - prompt="List me all the projects with their description", - source="https://perinim.github.io", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/together/document_scraper_together.py b/examples/together/document_scraper_together.py deleted file mode 100644 index c3324330..00000000 --- a/examples/together/document_scraper_together.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -document_scraper example -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import DocumentScraperGraph - -load_dotenv() - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -source = """ - The Divine Comedy, Italian La Divina Commedia, original name La commedia, long narrative poem written in Italian - circa 1308/21 by Dante. It is usually held to be one of the world s great works of literature. - Divided into three major sections—Inferno, Purgatorio, and Paradiso—the narrative traces the journey of Dante - from darkness and error to the revelation of the divine light, culminating in the Beatific Vision of God. - Dante is guided by the Roman poet Virgil, who represents the epitome of human knowledge, from the dark wood - through the descending circles of the pit of Hell (Inferno). He then climbs the mountain of Purgatory, guided - by the Roman poet Statius, who represents the fulfilment of human knowledge, and is finally led by his lifelong love, - the Beatrice of his earlier poetry, through the celestial spheres of Paradise. -""" - -pdf_scraper_graph = DocumentScraperGraph( - prompt="Summarize the text and find the main topics", - source=source, - config=graph_config, -) -result = pdf_scraper_graph.run() - -print(json.dumps(result, indent=4)) \ No newline at end of file diff --git a/examples/together/inputs/books.xml b/examples/together/inputs/books.xml deleted file mode 100644 index e3d1fe87..00000000 --- a/examples/together/inputs/books.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Gambardella, Matthew - XML Developer's Guide - Computer - 44.95 - 2000-10-01 - An in-depth look at creating applications - with XML. - - - Ralls, Kim - Midnight Rain - Fantasy - 5.95 - 2000-12-16 - A former architect battles corporate zombies, - an evil sorceress, and her own childhood to become queen - of the world. - - - Corets, Eva - Maeve Ascendant - Fantasy - 5.95 - 2000-11-17 - After the collapse of a nanotechnology - society in England, the young survivors lay the - foundation for a new society. - - - Corets, Eva - Oberon's Legacy - Fantasy - 5.95 - 2001-03-10 - In post-apocalypse England, the mysterious - agent known only as Oberon helps to create a new life - for the inhabitants of London. Sequel to Maeve - Ascendant. - - - Corets, Eva - The Sundered Grail - Fantasy - 5.95 - 2001-09-10 - The two daughters of Maeve, half-sisters, - battle one another for control of England. Sequel to - Oberon's Legacy. - - - Randall, Cynthia - Lover Birds - Romance - 4.95 - 2000-09-02 - When Carla meets Paul at an ornithology - conference, tempers fly as feathers get ruffled. - - - Thurman, Paula - Splish Splash - Romance - 4.95 - 2000-11-02 - A deep sea diver finds true love twenty - thousand leagues beneath the sea. - - - Knorr, Stefan - Creepy Crawlies - Horror - 4.95 - 2000-12-06 - An anthology of horror stories about roaches, - centipedes, scorpions and other insects. - - - Kress, Peter - Paradox Lost - Science Fiction - 6.95 - 2000-11-02 - After an inadvertant trip through a Heisenberg - Uncertainty Device, James Salway discovers the problems - of being quantum. - - - O'Brien, Tim - Microsoft .NET: The Programming Bible - Computer - 36.95 - 2000-12-09 - Microsoft's .NET initiative is explored in - detail in this deep programmer's reference. - - - O'Brien, Tim - MSXML3: A Comprehensive Guide - Computer - 36.95 - 2000-12-01 - The Microsoft MSXML3 parser is covered in - detail, with attention to XML DOM interfaces, XSLT processing, - SAX and more. - - - Galos, Mike - Visual Studio 7: A Comprehensive Guide - Computer - 49.95 - 2001-04-16 - Microsoft Visual Studio 7 is explored in depth, - looking at how Visual Basic, Visual C++, C#, and ASP+ are - integrated into a comprehensive development - environment. - - \ No newline at end of file diff --git a/examples/together/inputs/example.json b/examples/together/inputs/example.json deleted file mode 100644 index 2263184c..00000000 --- a/examples/together/inputs/example.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "kind":"youtube#searchListResponse", - "etag":"q4ibjmYp1KA3RqMF4jFLl6PBwOg", - "nextPageToken":"CAUQAA", - "regionCode":"NL", - "pageInfo":{ - "totalResults":1000000, - "resultsPerPage":5 - }, - "items":[ - { - "kind":"youtube#searchResult", - "etag":"QCsHBifbaernVCbLv8Cu6rAeaDQ", - "id":{ - "kind":"youtube#video", - "videoId":"TvWDY4Mm5GM" - }, - "snippet":{ - "publishedAt":"2023-07-24T14:15:01Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Football Clubs Kylian Mbappe Should Avoid Signing ✍️❌⚽️ #football #mbappe #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/TvWDY4Mm5GM/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T14:15:01Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"0NG5QHdtIQM_V-DBJDEf-jK_Y9k", - "id":{ - "kind":"youtube#video", - "videoId":"aZM_42CcNZ4" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:09:27Z", - "channelId":"UCM5gMM_HqfKHYIEJ3lstMUA", - "title":"Which Football Club Could Cristiano Ronaldo Afford To Buy? 💰", - "description":"Sign up to Sorare and get a FREE card: https://sorare.pxf.io/NellisShorts Give Soraredata a go for FREE: ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/aZM_42CcNZ4/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"John Nellis", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:09:27Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"WbBz4oh9I5VaYj91LjeJvffrBVY", - "id":{ - "kind":"youtube#video", - "videoId":"wkP3XS3aNAY" - }, - "snippet":{ - "publishedAt":"2023-07-24T16:00:50Z", - "channelId":"UC4EP1dxFDPup_aFLt0ElsDw", - "title":"PAULO DYBALA vs THE WORLD'S LONGEST FREEKICK WALL", - "description":"Can Paulo Dybala curl a football around the World's longest free kick wall? We met up with the World Cup winner and put him to ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/wkP3XS3aNAY/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Shoot for Love", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T16:00:50Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"juxv_FhT_l4qrR05S1QTrb4CGh8", - "id":{ - "kind":"youtube#video", - "videoId":"rJkDZ0WvfT8" - }, - "snippet":{ - "publishedAt":"2023-07-24T10:00:39Z", - "channelId":"UCO8qj5u80Ga7N_tP3BZWWhQ", - "title":"TOP 10 DEFENDERS 2023", - "description":"SoccerKingz https://soccerkingz.nl Use code: 'ILOVEHOF' to get 10% off. TOP 10 DEFENDERS 2023 Follow us! • Instagram ...", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/rJkDZ0WvfT8/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"Home of Football", - "liveBroadcastContent":"none", - "publishTime":"2023-07-24T10:00:39Z" - } - }, - { - "kind":"youtube#searchResult", - "etag":"wtuknXTmI1txoULeH3aWaOuXOow", - "id":{ - "kind":"youtube#video", - "videoId":"XH0rtu4U6SE" - }, - "snippet":{ - "publishedAt":"2023-07-21T16:30:05Z", - "channelId":"UCwozCpFp9g9x0wAzuFh0hwQ", - "title":"3 Things You Didn't Know About Erling Haaland ⚽️🇳🇴 #football #haaland #shorts", - "description":"", - "thumbnails":{ - "default":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/default.jpg", - "width":120, - "height":90 - }, - "medium":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/mqdefault.jpg", - "width":320, - "height":180 - }, - "high":{ - "url":"https://i.ytimg.com/vi/XH0rtu4U6SE/hqdefault.jpg", - "width":480, - "height":360 - } - }, - "channelTitle":"FC Motivate", - "liveBroadcastContent":"none", - "publishTime":"2023-07-21T16:30:05Z" - } - } - ] -} \ No newline at end of file diff --git a/examples/together/inputs/username.csv b/examples/together/inputs/username.csv deleted file mode 100644 index 006ac8e6..00000000 --- a/examples/together/inputs/username.csv +++ /dev/null @@ -1,7 +0,0 @@ -Username; Identifier;First name;Last name -booker12;9012;Rachel;Booker -grey07;2070;Laura;Grey -johnson81;4081;Craig;Johnson -jenkins46;9346;Mary;Jenkins -smith79;5079;Jamie;Smith - diff --git a/examples/together/json_scraper_multi_together.py b/examples/together/json_scraper_multi_together.py deleted file mode 100644 index 0d9ac293..00000000 --- a/examples/together/json_scraper_multi_together.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Module for showing how JSONScraperMultiGraph multi works -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperMultiGraph - -load_dotenv() - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -sources = [text, text] - -multiple_search_graph = JSONScraperMultiGraph( - prompt= "List me all the authors, title and genres of the books", - source= sources, - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/together/json_scraper_together.py b/examples/together/json_scraper_together.py deleted file mode 100644 index a39c6ce4..00000000 --- a/examples/together/json_scraper_together.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Basic example of scraping pipeline using JSONScraperGraph from JSON documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import JSONScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the JSON file -# ************************************************ -together_key = os.getenv("TOGETHER_APIKEY") - -FILE_NAME = "inputs/example.json" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the JSONScraperGraph instance and run it -# ************************************************ - -json_scraper_graph = JSONScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = json_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = json_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/together/rate_limit_together.py b/examples/together/rate_limit_together.py deleted file mode 100644 index 89e3f89f..00000000 --- a/examples/together/rate_limit_together.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper with a custom rate limit -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - "rate_limit": { - "requests_per_second": 1 - } - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/together/scrape_plain_text_together.py b/examples/together/scrape_plain_text_together.py deleted file mode 100644 index feff1e3a..00000000 --- a/examples/together/scrape_plain_text_together.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper from text -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the text file -# ************************************************ - -FILE_NAME = "inputs/plain_html_example.txt" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -# It could be also a http request using the request model -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the news with their description.", - source=text, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/together/script_generator_together.py b/examples/together/script_generator_together.py deleted file mode 100644 index cfe46c83..00000000 --- a/examples/together/script_generator_together.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects", - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/together/script_multi_generator_together.py b/examples/together/script_multi_generator_together.py deleted file mode 100644 index 0596f1e2..00000000 --- a/examples/together/script_multi_generator_together.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Basic example of scraping pipeline using ScriptCreatorGraph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import ScriptCreatorMultiGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "library": "beautifulsoup" -} - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -urls=[ - "https://schultzbergagency.com/emil-raste-karlsen/", - "https://schultzbergagency.com/johanna-hedberg/", -] - -# ************************************************ -# Create the ScriptCreatorGraph instance and run it -# ************************************************ - -script_creator_graph = ScriptCreatorMultiGraph( - prompt="Find information about actors", - # also accepts a string with the already downloaded HTML code - source=urls, - config=graph_config -) - -result = script_creator_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = script_creator_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/together/search_graph_schema_together.py b/examples/together/search_graph_schema_together.py deleted file mode 100644 index c5954294..00000000 --- a/examples/together/search_graph_schema_together.py +++ /dev/null @@ -1,61 +0,0 @@ -""" -Example of Search Graph -""" - -import os -from typing import List -from pydantic import BaseModel, Field -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Dish(BaseModel): - name: str = Field(description="The name of the dish") - description: str = Field(description="The description of the dish") - -class Dishes(BaseModel): - dishes: List[Dish] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me Chioggia's famous dishes", - config=graph_config, - schema=Dishes -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/together/search_graph_together.py b/examples/together/search_graph_together.py deleted file mode 100644 index e4c442c4..00000000 --- a/examples/together/search_graph_together.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "max_results": 2, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) diff --git a/examples/together/search_link_graph_together.py b/examples/together/search_link_graph_together.py deleted file mode 100644 index 46c86d5c..00000000 --- a/examples/together/search_link_graph_together.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -Example of Search Graph -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SearchGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -load_dotenv() - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SearchGraph instance and run it -# ************************************************ - -search_graph = SearchGraph( - prompt="List me the best escursions near Trento", - config=graph_config -) - -result = search_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = search_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json and csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/together/smart_scraper_lite_together.py b/examples/together/smart_scraper_lite_together.py deleted file mode 100644 index 0519ecba..00000000 --- a/examples/together/smart_scraper_lite_together.py +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/together/smart_scraper_multi_lite_together.py b/examples/together/smart_scraper_multi_lite_together.py deleted file mode 100644 index 8cf66dea..00000000 --- a/examples/together/smart_scraper_multi_lite_together.py +++ /dev/null @@ -1,43 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiLiteGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_multi_lite_graph = SmartScraperMultiLiteGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - config=graph_config -) - -result = smart_scraper_multi_lite_graph.run() -print(json.dumps(result, indent=4)) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_multi_lite_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/together/smart_scraper_multi_together.py b/examples/together/smart_scraper_multi_together.py deleted file mode 100644 index a2da7b8f..00000000 --- a/examples/together/smart_scraper_multi_together.py +++ /dev/null @@ -1,40 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -import json -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperMultiGraph - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ******************************************************* -# Create the SmartScraperMultiGraph instance and run it -# ******************************************************* - -multiple_search_graph = SmartScraperMultiGraph( - prompt="Who is Marco Perini?", - source= [ - "https://perinim.github.io/", - "https://perinim.github.io/cv/" - ], - schema=None, - config=graph_config -) - -result = multiple_search_graph.run() -print(json.dumps(result, indent=4)) diff --git a/examples/together/smart_scraper_schema_together.py b/examples/together/smart_scraper_schema_together.py deleted file mode 100644 index 45883ff0..00000000 --- a/examples/together/smart_scraper_schema_together.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from typing import List -from pydantic import BaseModel, Field -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the output schema for the graph -# ************************************************ - -class Project(BaseModel): - title: str = Field(description="The title of the project") - description: str = Field(description="The description of the project") - -class Projects(BaseModel): - projects: List[Project] - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - schema=Projects, - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/together/smart_scraper_together.py b/examples/together/smart_scraper_together.py deleted file mode 100644 index c60656f2..00000000 --- a/examples/together/smart_scraper_together.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Basic example of scraping pipeline using SmartScraper -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import SmartScraperGraph -from scrapegraphai.utils import prettify_exec_info - -load_dotenv() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the SmartScraperGraph instance and run it -# ************************************************ - -smart_scraper_graph = SmartScraperGraph( - prompt="List me all the projects with their description.", - # also accepts a string with the already downloaded HTML code - source="https://perinim.github.io/projects/", - config=graph_config -) - -result = smart_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = smart_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) diff --git a/examples/together/xml_scraper_graph_multi_together.py b/examples/together/xml_scraper_graph_multi_together.py deleted file mode 100644 index d6d98a0d..00000000 --- a/examples/together/xml_scraper_graph_multi_together.py +++ /dev/null @@ -1,58 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperMultiGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperMultiGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the XMLScraperMultiGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperMultiGraph( - prompt="List me all the authors, title and genres of the books", - source=[text, text], # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/together/xml_scraper_together.py b/examples/together/xml_scraper_together.py deleted file mode 100644 index b1d39e2e..00000000 --- a/examples/together/xml_scraper_together.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Basic example of scraping pipeline using XMLScraperGraph from XML documents -""" -import os -from dotenv import load_dotenv -from scrapegraphai.graphs import XMLScraperGraph -from scrapegraphai.utils import convert_to_csv, convert_to_json, prettify_exec_info - -load_dotenv() - -# ************************************************ -# Read the XML file -# ************************************************ - -FILE_NAME = "inputs/books.xml" -curr_dir = os.path.dirname(os.path.realpath(__file__)) -file_path = os.path.join(curr_dir, FILE_NAME) - -with open(file_path, 'r', encoding="utf-8") as file: - text = file.read() - -# ************************************************ -# Define the configuration for the graph -# ************************************************ - - -together_key = os.getenv("TOGETHER_APIKEY") - -graph_config = { - "llm": { - "model": "togetherai/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", - "api_key": together_key, - }, - "verbose": True, -} - -# ************************************************ -# Create the XMLScraperGraph instance and run it -# ************************************************ - -xml_scraper_graph = XMLScraperGraph( - prompt="List me all the authors, title and genres of the books", - source=text, # Pass the content of the file, not the file object - config=graph_config -) - -result = xml_scraper_graph.run() -print(result) - -# ************************************************ -# Get graph execution info -# ************************************************ - -graph_exec_info = xml_scraper_graph.get_execution_info() -print(prettify_exec_info(graph_exec_info)) - -# Save to json or csv -convert_to_csv(result, "result") -convert_to_json(result, "result") diff --git a/examples/xml_scraper_graph/.env.example b/examples/xml_scraper_graph/.env.example new file mode 100644 index 00000000..9f0d484b --- /dev/null +++ b/examples/xml_scraper_graph/.env.example @@ -0,0 +1,11 @@ +# OpenAI API Configuration +OPENAI_API_KEY=your-openai-api-key-here + +# Optional Configurations +MAX_TOKENS=4000 +MODEL_NAME=gpt-4-1106-preview +TEMPERATURE=0.7 + +# XML Scraper Settings +XPATH_TIMEOUT=30 +VALIDATE_XML=true \ No newline at end of file diff --git a/examples/xml_scraper_graph/README.md b/examples/xml_scraper_graph/README.md new file mode 100644 index 00000000..ed7eaf30 --- /dev/null +++ b/examples/xml_scraper_graph/README.md @@ -0,0 +1,30 @@ +# XML Scraper Graph Example + +This example demonstrates how to use Scrapegraph-ai to extract and process XML data from web sources. + +## Features + +- XML data extraction +- XPath querying +- Data transformation +- Schema validation + +## Setup + +1. Install required dependencies +2. Copy `.env.example` to `.env` +3. Configure your API keys in the `.env` file + +## Usage + +```python +from scrapegraphai.graphs import XmlScraperGraph + +graph = XmlScraperGraph() +xml_data = graph.scrape("https://example.com/feed.xml") +``` + +## Environment Variables + +Required environment variables: +- `OPENAI_API_KEY`: Your OpenAI API key \ No newline at end of file diff --git a/examples/anthropic/inputs/books.xml b/examples/xml_scraper_graph/ollama/inputs/books.xml similarity index 100% rename from examples/anthropic/inputs/books.xml rename to examples/xml_scraper_graph/ollama/inputs/books.xml diff --git a/examples/local_models/xml_scraper_graph_multi_ollama.py b/examples/xml_scraper_graph/ollama/xml_scraper_graph_multi_ollama.py similarity index 100% rename from examples/local_models/xml_scraper_graph_multi_ollama.py rename to examples/xml_scraper_graph/ollama/xml_scraper_graph_multi_ollama.py diff --git a/examples/local_models/xml_scraper_ollama.py b/examples/xml_scraper_graph/ollama/xml_scraper_ollama.py similarity index 100% rename from examples/local_models/xml_scraper_ollama.py rename to examples/xml_scraper_graph/ollama/xml_scraper_ollama.py diff --git a/examples/azure/inputs/books.xml b/examples/xml_scraper_graph/openai/inputs/books.xml similarity index 100% rename from examples/azure/inputs/books.xml rename to examples/xml_scraper_graph/openai/inputs/books.xml diff --git a/examples/openai/xml_scraper_graph_multi_openai.py b/examples/xml_scraper_graph/openai/xml_scraper_graph_multi_openai.py similarity index 100% rename from examples/openai/xml_scraper_graph_multi_openai.py rename to examples/xml_scraper_graph/openai/xml_scraper_graph_multi_openai.py diff --git a/examples/openai/xml_scraper_openai.py b/examples/xml_scraper_graph/openai/xml_scraper_openai.py similarity index 100% rename from examples/openai/xml_scraper_openai.py rename to examples/xml_scraper_graph/openai/xml_scraper_openai.py diff --git a/scrapegraphai/nodes/merge_answers_node.py b/scrapegraphai/nodes/merge_answers_node.py index 77eb1587..b867b3e0 100644 --- a/scrapegraphai/nodes/merge_answers_node.py +++ b/scrapegraphai/nodes/merge_answers_node.py @@ -5,6 +5,7 @@ from typing import List, Optional from langchain.prompts import PromptTemplate +from langchain_community.chat_models import ChatOllama from langchain_core.output_parsers import JsonOutputParser from langchain_mistralai import ChatMistralAI from langchain_openai import ChatOpenAI @@ -42,6 +43,13 @@ def __init__( super().__init__(node_name, "node", input, output, 2, node_config) self.llm_model = node_config["llm_model"] + + if isinstance(self.llm_model, ChatOllama): + if self.node_config.get("schema", None) is None: + self.llm_model.format = "json" + else: + self.llm_model.format = self.node_config["schema"].model_json_schema() + self.verbose = ( False if node_config is None else node_config.get("verbose", False) )