Преглед изворни кода

Refactor: Implement in-memory Qdrant and secure API keys; Update README

llamatest пре 5 дана
родитељ
комит
e2b3cac829

+ 1 - 0
end-to-end-use-cases/technical_blogger/.env

@@ -0,0 +1 @@
+LLAMA_API_KEY="Add your API key here"

+ 164 - 0
end-to-end-use-cases/technical_blogger/Building_a_Messenger_Chatbot_with_Llama_3_blog.md

@@ -0,0 +1,164 @@
+# Building a Messenger Chatbot with Llama 3
+
+Building a Messenger Chatbot with Llama 3: A Step-by-Step Guide
+=============================================================
+
+### Introduction
+
+In this blog post, we'll explore the process of building a Llama 3 enabled Messenger chatbot using the Messenger Platform. We'll cover the architectural components, setup instructions, and best practices to help you get started.
+
+### Overview of the Messenger Platform
+
+The Messenger Platform is a powerful tool that allows businesses to connect with their customers through a Facebook business page. By integrating Llama 3 with the Messenger Platform, businesses can create intelligent and knowledgeable chatbots that provide 24x7 customer support, improving customer experience and reducing costs.
+
+### Architectural Components
+
+The diagram below illustrates the components and overall data flow of the Llama 3 enabled Messenger chatbot demo:
+```markdown
++---------------+
+|  User         |
+|  (Messenger    |
+|   App)         |
++---------------+
+       |
+       |  (1) Send Message
+       v
++---------------+
+|  Facebook      |
+|  Business Page  |
++---------------+
+       |
+       |  (2) Webhook Event
+       v
++---------------+
+|  Web Server    |
+|  (e.g., Amazon  |
+|   EC2 instance)  |
++---------------+
+       |
+       |  (3) Process Event
+       |  and Generate Response
+       |  using Llama 3
+       v
++---------------+
+|  Llama 3       |
+|  Model         |
++---------------+
+       |
+       |  (4) Send Response
+       |  back to User
+       v
++---------------+
+|  Facebook      |
+|  Business Page  |
++---------------+
+       |
+       |  (5) Receive Response
+       v
++---------------+
+|  User         |
+|  (Messenger    |
+|   App)         |
++---------------+
+```
+The components involved are:
+
+*   **User**: The customer interacting with the Facebook business page using the Messenger app.
+*   **Facebook Business Page**: The business page that receives user messages and sends responses.
+*   **Web Server**: The server that processes incoming webhook events, generates responses using Llama 3, and sends responses back to the user.
+*   **Llama 3 Model**: The AI model that generates human-like responses to user queries.
+
+### Setup Instructions
+
+To build a Llama 3 enabled Messenger chatbot, follow these steps:
+
+#### Step 1: Create a Facebook Business Page
+
+1.  Go to the Facebook Business Page creation page and follow the instructions to create a new page.
+2.  Ensure that you have the necessary permissions to manage the page.
+
+#### Step 2: Set up a Web Server
+
+1.  Choose a cloud provider (e.g., Amazon Web Services) and launch an EC2 instance to host your web server.
+2.  Configure the instance with the necessary dependencies, such as Node.js and a webhook event handler.
+
+Here's an example of a basic Node.js server using Express.js:
+```javascript
+const express = require('express');
+const app = express();
+
+app.use(express.json());
+
+app.post('/webhook', (req, res) => {
+    // Process webhook event
+    const event = req.body;
+    // Generate response using Llama 3
+    const response = generateResponse(event);
+    // Send response back to user
+    sendResponse(response);
+    res.status(200).send('EVENT_RECEIVED');
+});
+
+app.listen(3000, () => {
+    console.log('Server listening on port 3000');
+});
+```
+#### Step 3: Integrate Llama 3 with the Web Server
+
+1.  Install the necessary dependencies for Llama 3, such as the Llama 3 Python library.
+2.  Implement a function to generate responses using Llama 3.
+
+Here's an example of a Python function that generates a response using Llama 3:
+```python
+import llama
+
+def generate_response(event):
+    # Initialize Llama 3 model
+    model = llama.Llama3()
+    # Process event and generate response
+    response = model.generate(event['message'])
+    return response
+```
+#### Step 4: Configure Webhook Events
+
+1.  Go to the Facebook Developer Dashboard and navigate to your app's settings.
+2.  Configure the webhook events to send incoming messages to your web server.
+
+Here's an example of a webhook event configuration:
+```json
+{
+    "object": "page",
+    "entry": [
+        {
+            "id": "PAGE_ID",
+            "time": 1643723400,
+            "messaging": [
+                {
+                    "sender": {
+                        "id": "USER_ID"
+                    },
+                    "recipient": {
+                        "id": "PAGE_ID"
+                    },
+                    "timestamp": 1643723400,
+                    "message": {
+                        "text": "Hello, how are you?"
+                    }
+                }
+            ]
+        }
+    ]
+}
+```
+#### Step 5: Test the Chatbot
+
+1.  Use the Messenger app to send a message to your Facebook business page.
+2.  Verify that the chatbot responds with a relevant answer generated by Llama 3.
+
+### Best Practices
+
+*   Ensure that your web server is secure and scalable to handle a large volume of incoming requests.
+*   Implement logging and monitoring to track chatbot performance and identify areas for improvement.
+*   Continuously update and fine-tune your Llama 3 model to improve response accuracy and relevance.
+
+By following these steps and best practices, you can build a Llama 3 enabled Messenger chatbot that provides an engaging and informative customer experience.

+ 689 - 0
end-to-end-use-cases/technical_blogger/Technical_Blog_Generator.ipynb

@@ -0,0 +1,689 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "a0eaff04",
+   "metadata": {},
+   "source": [
+    "# Ensure the required libraries are installed i.e.\n",
+    "!pip install sentence-transformers qdrant-client requests IPython\n"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4a8cdfac",
+   "metadata": {},
+   "source": [
+    "# Step 1: Import necessary modules"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "b3f67c91",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Libraries installed and modules imported successfully.\n"
+     ]
+    }
+   ],
+   "source": [
+    "import os\n",
+    "import uuid\n",
+    "import re\n",
+    "from pathlib import Path\n",
+    "from sentence_transformers import SentenceTransformer, CrossEncoder\n",
+    "from qdrant_client import QdrantClient, models\n",
+    "from qdrant_client.models import SearchRequest\n",
+    "import requests\n",
+    "from IPython.display import Markdown, display\n",
+    "import json\n",
+    "\n",
+    "print(\"Libraries installed and modules imported successfully.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "58a4962f",
+   "metadata": {},
+   "source": [
+    "# Step 2: Define Configuration and Global Variables\n",
+    "This contains all your static configuration, including API keys, URLs, and file paths."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "01e548da",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Configuration variables and collection name set.\n"
+     ]
+    }
+   ],
+   "source": [
+    "# --- Configuration ---\n",
+    "# API Keys should be loaded from environment variables for security.\n",
+    "# DO NOT commit your .env file or hardcode API keys directly in the code for production.\n",
+    "\n",
+    "\n",
+    "LLAMA_API_KEY = os.getenv(\"LLAMA_API_KEY\")\n",
+    "if not LLAMA_API_KEY:\n",
+    "    raise ValueError(\"LLAMA_API_KEY not found. Please set it as an environment variable or in a .env file.\")\n",
+    "\n",
+    "API_URL = \"https://api.llama.com/v1/chat/completions\"\n",
+    "HEADERS = {\n",
+    "    \"Content-Type\": \"application/json\",\n",
+    "    \"Authorization\": f\"Bearer {LLAMA_API_KEY}\"\n",
+    "}\n",
+    "LLAMA_MODEL = \"Llama-4-Maverick-17B-128E-Instruct-FP8\"\n",
+    "\n",
+    "# Qdrant Configuration (Now using In-Memory Qdrant for offline use)\n",
+    "# No QDRANT_URL or QDRANT_API_KEY needed for in-memory client.\n",
+    "\n",
+    "# The Qdrant collection to be queried. This will be created in-memory.\n",
+    "MAIN_COLLECTION_NAME = \"readme_blogs_latest\"\n",
+    "\n",
+    "print(\"Configuration variables and collection name set.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "d76eccb5",
+   "metadata": {},
+   "source": [
+    "# Step 3: Define Helper Functions\n",
+    "It contains all the functions that handle the core logic of the application: markdown_splitter, setup_qdrant, and query_qdrant."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "2b972b21",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Helper functions for querying Qdrant defined.\n"
+     ]
+    }
+   ],
+   "source": [
+    "def get_qdrant_client():\n",
+    "    \"\"\"Returns an in-memory Qdrant client instance.\"\"\"\n",
+    "    # For an in-memory client, you don't pass URL or API Key.\n",
+    "    return QdrantClient(\":memory:\")\n",
+    "\n",
+    "def get_embedding_model():\n",
+    "    \"\"\"Returns the SentenceTransformer embedding model.\"\"\"\n",
+    "    return SentenceTransformer('all-MiniLM-L6-v2')\n",
+    "\n",
+    "def create_qdrant_collection(client, collection_name, vector_size):\n",
+    "    \"\"\"Creates a Qdrant collection with the specified vector size if it doesn't exist.\"\"\"\n",
+    "    try:\n",
+    "        # Check if collection exists\n",
+    "        client.get_collection(collection_name=collection_name)\n",
+    "        print(f\"Collection '{collection_name}' already exists.\")\n",
+    "    except Exception: # QdrantClient throws if collection doesn't exist\n",
+    "        print(f\"Creating collection '{collection_name}'...\")\n",
+    "        client.recreate_collection(\n",
+    "            collection_name=collection_name,\n",
+    "            vectors_config=models.VectorParams(size=vector_size, distance=models.Distance.COSINE),\n",
+    "        )\n",
+    "        print(f\"Collection '{collection_name}' created.\")\n",
+    "\n",
+    "def ingest_data_into_qdrant(client, collection_name, embedding_model, data_chunks):\n",
+    "    \"\"\"\n",
+    "    Ingests data (text chunks) into the Qdrant collection.\n",
+    "    You will need to replace this with your actual data loading and chunking logic.\n",
+    "    \"\"\"\n",
+    "    print(f\"Ingesting data into collection '{collection_name}'...\")\n",
+    "    if not data_chunks:\n",
+    "        print(\"No data chunks provided for ingestion.\")\n",
+    "        return\n",
+    "\n",
+    "    points = []\n",
+    "    for i, chunk_text in enumerate(data_chunks):\n",
+    "        embedding = embedding_model.encode(chunk_text).tolist()\n",
+    "        points.append(\n",
+    "            models.PointStruct(\n",
+    "                id=i, # Unique ID for each point\n",
+    "                vector=embedding,\n",
+    "                payload={\"text\": chunk_text}\n",
+    "            )\n",
+    "        )\n",
+    "    \n",
+    "    # Ensure the collection has been created with the correct vector size\n",
+    "    # before attempting to upsert.\n",
+    "    # The vector size must match the embedding model output.\n",
+    "    embedding_size = len(embedding_model.encode(\"test\").tolist())\n",
+    "    create_qdrant_collection(client, collection_name, embedding_size)\n",
+    "\n",
+    "    operation_info = client.upsert(\n",
+    "        collection_name=collection_name,\n",
+    "        wait=True,\n",
+    "        points=points,\n",
+    "    )\n",
+    "    print(f\"Data ingestion complete. Status: {operation_info.status}\")\n",
+    "\n",
+    "\n",
+    "def query_qdrant(query, client, collection_name, top_k=5):\n",
+    "    \"\"\"Query Qdrant with hybrid search and reranking on a specified collection.\"\"\"\n",
+    "    embedding_model = get_embedding_model()\n",
+    "    query_embedding = embedding_model.encode(query).tolist()\n",
+    "    \n",
+    "    # Initial vector search\n",
+    "    try:\n",
+    "        results = client.search(\n",
+    "            collection_name=collection_name,\n",
+    "            query_vector=query_embedding,\n",
+    "            limit=top_k*2\n",
+    "        )\n",
+    "    except Exception as e:\n",
+    "        print(f\"Error during Qdrant search on collection '{collection_name}': {e}\")\n",
+    "        return []\n",
+    "    \n",
+    "    if not results:\n",
+    "        print(\"No results found in Qdrant for the given query.\")\n",
+    "        return []\n",
+    "\n",
+    "    # Rerank using cross-encoder\n",
+    "    cross_encoder = CrossEncoder('cross-encoder/ms-marco-MiniLM-L6-v2')\n",
+    "    pairs = [(query, hit.payload[\"text\"]) for hit in results]\n",
+    "    scores = cross_encoder.predict(pairs)\n",
+    "    \n",
+    "    # Combine scores with results\n",
+    "    sorted_results = [x for _, x in sorted(zip(scores, results), key=lambda pair: pair[0], reverse=True)]\n",
+    "    return sorted_results[:top_k]\n",
+    "\n",
+    "print(\"Helper functions for querying Qdrant defined.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "092d8cd8",
+   "metadata": {},
+   "source": [
+    "# Step 4: Define the Main Blog Generation Function\n",
+    "This function orchestrates the RAG process by calling the helper functions, building the prompt, and making the API call."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "0d682099",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Blog generation function defined.\n"
+     ]
+    }
+   ],
+   "source": [
+    "def generate_blog(topic):\n",
+    "    \"\"\"Generates a technical blog post based on a topic using RAG.\"\"\"\n",
+    "    print(\"Getting Qdrant client and querying pre-existing collection...\")\n",
+    "    client = get_qdrant_client()\n",
+    "    embedding_model = get_embedding_model()\n",
+    "\n",
+    "    # IMPORTANT: For in-memory Qdrant, you MUST ingest your data every time\n",
+    "    # the script runs or the client is initialized, as it's not persistent.\n",
+    "    # Replace this with your actual data loading and chunking.\n",
+    "    # Example placeholder data:\n",
+    "    example_data_chunks = [\n",
+    "        \"Llama 3 is a powerful large language model developed by Meta. It excels at various NLP tasks.\",\n",
+    "        \"To build a chatbot with Llama 3, you'll typically use an API to send prompts and receive responses.\",\n",
+    "        \"Messenger Platform allows developers to create interactive experiences for Facebook Messenger users.\",\n",
+    "        \"Integrating Llama 3 with Messenger involves setting up webhooks and handling message events.\",\n",
+    "        \"Key steps include setting up a Facebook App, configuring webhooks, and deploying your bot's backend.\",\n",
+    "        \"Best practices for chatbots include clear error handling, concise responses, and user guidance.\",\n",
+    "        \"Security is crucial; always protect your API keys and ensure your webhook endpoints are secure.\"\n",
+    "    ]\n",
+    "    ingest_data_into_qdrant(client, MAIN_COLLECTION_NAME, embedding_model, example_data_chunks)\n",
+    "    # End of IMPORTANT section for data ingestion\n",
+    "\n",
+    "\n",
+    "    # Query relevant sections from the main collection\n",
+    "    relevant_chunks = query_qdrant(topic, client, MAIN_COLLECTION_NAME)\n",
+    "    \n",
+    "    if not relevant_chunks:\n",
+    "        error_message = \"No relevant content found in the knowledge base. Cannot generate blog post.\"\n",
+    "        print(error_message)\n",
+    "        return error_message\n",
+    "\n",
+    "    context = \"\\n\".join([chunk.payload[\"text\"] for chunk in relevant_chunks])\n",
+    "    \n",
+    "    system_prompt = f\"\"\"\n",
+    "    You are a technical writer specializing in creating comprehensive documentation-based blog posts. \n",
+    "    Use the following context from technical documentation to write an in-depth blog post about {topic}.\n",
+    "    \n",
+    "    Requirements:\n",
+    "    1. Structure the blog with clear sections and subsections\n",
+    "    2. Include code examples and configuration details where relevant\n",
+    "    3. Explain architectural components using diagrams (describe in markdown)\n",
+    "    4. Add setup instructions and best practices\n",
+    "    5. Use technical terminology appropriate for developers\n",
+    "    \n",
+    "    Context:\n",
+    "    {context}\n",
+    "    \"\"\"\n",
+    "    \n",
+    "    payload = {\n",
+    "        \"model\": LLAMA_MODEL,\n",
+    "        \"messages\": [\n",
+    "            {\"role\": \"system\", \"content\": system_prompt},\n",
+    "            {\"role\": \"user\", \"content\": f\"Write a detailed technical blog post about {topic}\"}\n",
+    "        ],\n",
+    "        \"temperature\": 0.5,\n",
+    "        \"max_tokens\": 4096\n",
+    "    }\n",
+    "    \n",
+    "    print(\"Sending request to Llama API for blog generation...\")\n",
+    "    try:\n",
+    "        response = requests.post(API_URL, headers=HEADERS, json=payload)\n",
+    "        \n",
+    "        if response.status_code == 200:\n",
+    "            response_json = response.json()\n",
+    "            # Adjusting to handle the potentially nested structure as seen in your original code\n",
+    "            # where 'completion_message' might be missing or 'content' might be missing.\n",
+    "            # Adding .get with default values for safer access.\n",
+    "            blog_content = response_json.get('completion_message', {}).get('content', {}).get('text', '')\n",
+    "            \n",
+    "            if not blog_content:\n",
+    "                print(\"Warning: 'completion_message.content.text' was empty or not found in API response.\")\n",
+    "                print(f\"Full API response: {response_json}\")\n",
+    "                return \"Error: Could not extract blog content from API response.\"\n",
+    "\n",
+    "            # Format as markdown\n",
+    "            markdown_content = f\"# {topic}\\n\\n{blog_content}\"\n",
+    "            \n",
+    "            # Save to file\n",
+    "            output_path = Path(f\"{topic.replace(' ', '_')}_blog.md\")\n",
+    "            with open(output_path, \"w\", encoding=\"utf-8\") as f:\n",
+    "                f.write(markdown_content)\n",
+    "            \n",
+    "            print(f\"Blog post generated and saved to {output_path}.\")\n",
+    "            \n",
+    "            # Display markdown content directly in the notebook\n",
+    "            display(Markdown(markdown_content))\n",
+    "            return markdown_content\n",
+    "            \n",
+    "        else:\n",
+    "            error_message = f\"Error: {response.status_code} - {response.text}\"\n",
+    "            print(error_message)\n",
+    "            return error_message\n",
+    "    \n",
+    "    except Exception as e:\n",
+    "        error_message = f\"An unexpected error occurred: {str(e)}\"\n",
+    "        print(error_message)\n",
+    "        return error_message\n",
+    "\n",
+    "print(\"Blog generation function defined.\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "67497a92",
+   "metadata": {},
+   "source": [
+    "# Step 5: Specify the topic for the blog post and execute the Blog Generation Process\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6b3113ef",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Getting Qdrant client and querying pre-existing collection...\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/var/folders/f5/lntr7_gx6fd1y_1rtgwf2g9h0000gn/T/ipykernel_89390/3804544503.py:16: DeprecationWarning: `search` method is deprecated and will be removed in the future. Use `query_points` instead.\n",
+      "  results = client.search(\n"
+     ]
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "f0623176afc44a00ac97aa280a104140",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "config.json:   0%|          | 0.00/794 [00:00<?, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "bf7cfa830d6945c099716abd819fd652",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "model.safetensors:   0%|          | 0.00/90.9M [00:00<?, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "6b3a805cb1d04d659b0cda97fee10189",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "tokenizer_config.json: 0.00B [00:00, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "4a44a1a1123c4ea3960c454c260d7d01",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "vocab.txt: 0.00B [00:00, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "87a76d03243d4179849421448a3bd59e",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "tokenizer.json: 0.00B [00:00, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "7178785c5aaa4c02bd3f92277b67cb9f",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "special_tokens_map.json:   0%|          | 0.00/132 [00:00<?, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "04882361094c4a8e892c5c8d5b9e36a3",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "README.md: 0.00B [00:00, ?B/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Sending request to Llama API for blog generation...\n",
+      "Blog post generated and saved to Building_a_Messenger_Chatbot_with_Llama_3_blog.md.\n"
+     ]
+    },
+    {
+     "data": {
+      "text/markdown": [
+       "# Building a Messenger Chatbot with Llama 3\n",
+       "\n",
+       "Building a Messenger Chatbot with Llama 3: A Step-by-Step Guide\n",
+       "=============================================================\n",
+       "\n",
+       "### Introduction\n",
+       "\n",
+       "In this blog post, we'll explore the process of building a Llama 3 enabled Messenger chatbot using the Messenger Platform. We'll cover the architectural components, setup instructions, and best practices to help you get started.\n",
+       "\n",
+       "### Overview of the Messenger Platform\n",
+       "\n",
+       "The Messenger Platform is a powerful tool that allows businesses to connect with their customers through a Facebook business page. By integrating Llama 3 with the Messenger Platform, businesses can create intelligent and knowledgeable chatbots that provide 24x7 customer support, improving customer experience and reducing costs.\n",
+       "\n",
+       "### Architectural Components\n",
+       "\n",
+       "The diagram below illustrates the components and overall data flow of the Llama 3 enabled Messenger chatbot demo:\n",
+       "```markdown\n",
+       "+---------------+\n",
+       "|  User         |\n",
+       "|  (Messenger    |\n",
+       "|   App)         |\n",
+       "+---------------+\n",
+       "       |\n",
+       "       |  (1) Send Message\n",
+       "       v\n",
+       "+---------------+\n",
+       "|  Facebook      |\n",
+       "|  Business Page  |\n",
+       "+---------------+\n",
+       "       |\n",
+       "       |  (2) Webhook Event\n",
+       "       v\n",
+       "+---------------+\n",
+       "|  Web Server    |\n",
+       "|  (e.g., Amazon  |\n",
+       "|   EC2 instance)  |\n",
+       "+---------------+\n",
+       "       |\n",
+       "       |  (3) Process Event\n",
+       "       |  and Generate Response\n",
+       "       |  using Llama 3\n",
+       "       v\n",
+       "+---------------+\n",
+       "|  Llama 3       |\n",
+       "|  Model         |\n",
+       "+---------------+\n",
+       "       |\n",
+       "       |  (4) Send Response\n",
+       "       |  back to User\n",
+       "       v\n",
+       "+---------------+\n",
+       "|  Facebook      |\n",
+       "|  Business Page  |\n",
+       "+---------------+\n",
+       "       |\n",
+       "       |  (5) Receive Response\n",
+       "       v\n",
+       "+---------------+\n",
+       "|  User         |\n",
+       "|  (Messenger    |\n",
+       "|   App)         |\n",
+       "+---------------+\n",
+       "```\n",
+       "The components involved are:\n",
+       "\n",
+       "*   **User**: The customer interacting with the Facebook business page using the Messenger app.\n",
+       "*   **Facebook Business Page**: The business page that receives user messages and sends responses.\n",
+       "*   **Web Server**: The server that processes incoming webhook events, generates responses using Llama 3, and sends responses back to the user.\n",
+       "*   **Llama 3 Model**: The AI model that generates human-like responses to user queries.\n",
+       "\n",
+       "### Setup Instructions\n",
+       "\n",
+       "To build a Llama 3 enabled Messenger chatbot, follow these steps:\n",
+       "\n",
+       "#### Step 1: Create a Facebook Business Page\n",
+       "\n",
+       "1.  Go to the Facebook Business Page creation page and follow the instructions to create a new page.\n",
+       "2.  Ensure that you have the necessary permissions to manage the page.\n",
+       "\n",
+       "#### Step 2: Set up a Web Server\n",
+       "\n",
+       "1.  Choose a cloud provider (e.g., Amazon Web Services) and launch an EC2 instance to host your web server.\n",
+       "2.  Configure the instance with the necessary dependencies, such as Node.js and a webhook event handler.\n",
+       "\n",
+       "Here's an example of a basic Node.js server using Express.js:\n",
+       "```javascript\n",
+       "const express = require('express');\n",
+       "const app = express();\n",
+       "\n",
+       "app.use(express.json());\n",
+       "\n",
+       "app.post('/webhook', (req, res) => {\n",
+       "    // Process webhook event\n",
+       "    const event = req.body;\n",
+       "    // Generate response using Llama 3\n",
+       "    const response = generateResponse(event);\n",
+       "    // Send response back to user\n",
+       "    sendResponse(response);\n",
+       "    res.status(200).send('EVENT_RECEIVED');\n",
+       "});\n",
+       "\n",
+       "app.listen(3000, () => {\n",
+       "    console.log('Server listening on port 3000');\n",
+       "});\n",
+       "```\n",
+       "#### Step 3: Integrate Llama 3 with the Web Server\n",
+       "\n",
+       "1.  Install the necessary dependencies for Llama 3, such as the Llama 3 Python library.\n",
+       "2.  Implement a function to generate responses using Llama 3.\n",
+       "\n",
+       "Here's an example of a Python function that generates a response using Llama 3:\n",
+       "```python\n",
+       "import llama\n",
+       "\n",
+       "def generate_response(event):\n",
+       "    # Initialize Llama 3 model\n",
+       "    model = llama.Llama3()\n",
+       "    # Process event and generate response\n",
+       "    response = model.generate(event['message'])\n",
+       "    return response\n",
+       "```\n",
+       "#### Step 4: Configure Webhook Events\n",
+       "\n",
+       "1.  Go to the Facebook Developer Dashboard and navigate to your app's settings.\n",
+       "2.  Configure the webhook events to send incoming messages to your web server.\n",
+       "\n",
+       "Here's an example of a webhook event configuration:\n",
+       "```json\n",
+       "{\n",
+       "    \"object\": \"page\",\n",
+       "    \"entry\": [\n",
+       "        {\n",
+       "            \"id\": \"PAGE_ID\",\n",
+       "            \"time\": 1643723400,\n",
+       "            \"messaging\": [\n",
+       "                {\n",
+       "                    \"sender\": {\n",
+       "                        \"id\": \"USER_ID\"\n",
+       "                    },\n",
+       "                    \"recipient\": {\n",
+       "                        \"id\": \"PAGE_ID\"\n",
+       "                    },\n",
+       "                    \"timestamp\": 1643723400,\n",
+       "                    \"message\": {\n",
+       "                        \"text\": \"Hello, how are you?\"\n",
+       "                    }\n",
+       "                }\n",
+       "            ]\n",
+       "        }\n",
+       "    ]\n",
+       "}\n",
+       "```\n",
+       "#### Step 5: Test the Chatbot\n",
+       "\n",
+       "1.  Use the Messenger app to send a message to your Facebook business page.\n",
+       "2.  Verify that the chatbot responds with a relevant answer generated by Llama 3.\n",
+       "\n",
+       "### Best Practices\n",
+       "\n",
+       "*   Ensure that your web server is secure and scalable to handle a large volume of incoming requests.\n",
+       "*   Implement logging and monitoring to track chatbot performance and identify areas for improvement.\n",
+       "*   Continuously update and fine-tune your Llama 3 model to improve response accuracy and relevance.\n",
+       "\n",
+       "By following these steps and best practices, you can build a Llama 3 enabled Messenger chatbot that provides an engaging and informative customer experience."
+      ],
+      "text/plain": [
+       "<IPython.core.display.Markdown object>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "# Specify the topic for the blog post\n",
+    "topic = \"Building a Messenger Chatbot with Llama 3\"\n",
+    "\n",
+    "# Generate and display the blog content\n",
+    "blog_content = generate_blog(topic)\n",
+    "\n",
+    "if isinstance(blog_content, str) and \"Error\" in blog_content:\n",
+    "    print(blog_content)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "0930f7de",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "test_blogs",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.12.11"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}

Разлика између датотеке није приказан због своје велике величине
+ 24263 - 0
end-to-end-use-cases/technical_blogger/blog_metadata/3rd_party_integrations.txt


Разлика између датотеке није приказан због своје велике величине
+ 7900 - 0
end-to-end-use-cases/technical_blogger/blog_metadata/Getting_started_files.txt


Разлика између датотеке није приказан због своје велике величине
+ 5025 - 0
end-to-end-use-cases/technical_blogger/blog_metadata/mdfiles_latest.txt


+ 168 - 0
end-to-end-use-cases/technical_blogger/readme.md

@@ -0,0 +1,168 @@
+# Technical Blog Generator with RAG and Llama
+
+This project provides a practical recipe for building an AI-powered technical blog generator leveraging **Retrieval-Augmented Generation (RAG)**. It demonstrates how to combine the power of a Llama large language model (LLM) with a local, in-memory vector database (Qdrant) to synthesize accurate, relevant, and well-structured technical blog posts from your existing documentation.
+
+## Why RAG for Blog Generation?
+
+Integrating a Llama LLM with a vector database via a RAG approach offers significant advantages over using an LLM alone:
+
+* **Grounded Content**: The LLM is "grounded" in your specific technical documentation. This drastically reduces the likelihood of hallucinations and ensures the generated content is factually accurate and directly relevant to your knowledge base.
+* **Up-to-Date Information**: By updating your local knowledge base (the data you ingest into Qdrant), the system can stay current with the latest information without requiring the expensive and time-consuming process of retraining the entire LLM.
+* **Domain-Specific Expertise**: The generated blogs are enriched with precise, domain-specific details, including code snippets, configuration examples, and architectural explanations, all directly drawn from the provided context.
+* **Structured Output**: The system is prompted to produce highly structured output, featuring clear sections, subsections, and even descriptions for diagrams, making the blog post nearly ready for publication.
+
+## Architecture Overview
+
+The system follows a standard RAG pipeline, adapted for local development:
+
+1.  **Data Ingestion**: Your technical documentation is processed and split into smaller, semantically meaningful chunks of text.
+2.  **Indexing**: An embedding model (e.g., `all-MiniLM-L6-v2`) converts these text chunks into numerical vector embeddings. These vectors are then stored in an **in-memory Qdrant vector database**.
+3.  **Retrieval**: When a user specifies a blog topic, a query embedding is generated. This embedding is used to search the Qdrant database for the most relevant document chunks from your ingested knowledge base.
+4.  **Generation**: The retrieved relevant chunks, combined with the user's desired topic and a carefully crafted system prompt, are fed into the Llama model via its API. The Llama model then generates a comprehensive and detailed technical blog post based on this provided context.
+
+
+
+
++------------------+     +--------------------+     +-------------------+
+| Technical Docs   | --> | Data Chunking &    | --> | Embedding Model   |
+| (Raw Text Files) |     | Preprocessing      |     | (SentenceTrans.)  |
++------------------+     +--------------------+     +-------------------+
+|                                                    |
+v                                                    v
++-----------------------+                            +-----------------------+
+| In-Memory Qdrant DB   | <--------------------------| Vector Embeddings     |
+| (Knowledge Base)      | (Store Chunks & Embeddings)|                       |
++-----------------------+                            +-----------------------+
+^
+| (Query for relevant chunks)
++-----------------------+
+| User Input (Topic)    |
++-----------------------+
+|
+v
++-----------------------+     +-------------------+
+| Llama API             | <---| System Prompt     |
+| (Blog Generation)     |     | + Retrieved Chunks |
++-----------------------+     +-------------------+
+|
+v
++-----------------------+
+| Generated Technical   |
+| Blog Post (Markdown)  |
++-----------------------+
+
+
+
+
+## Prerequisites
+
+* Python 3.8 or higher
+* A Llama API key (obtained from [Llama's official site](https://www.llama.com/))
+* `pip` for installing Python packages
+
+## Getting Started
+
+Follow these steps to set up and run the technical blog generator.
+
+### Step 1: Clone the Repository
+
+First, clone the `llama-cookbook` repository and navigate to the specific recipe directory:
+
+```bash
+git clone [https://github.com/your-github-username/llama-cookbook.git](https://github.com/your-github-username/llama-cookbook.git) # Replace with actual repo URL if different
+cd llama-cookbook/end-to-end-use-cases/technical_blogger
+
+
+
+
+Step 2: Set Up Your Python Environment
+It's highly recommended to use a virtual environment to manage dependencies:
+
+Bash
+
+python -m venv .venv
+source .venv/bin/activate # On Windows: .venv\Scripts\activate
+pip install -r requirements.txt
+Note: Ensure you have a requirements.txt file in your technical_blogger directory listing all necessary libraries, such as qdrant-client, sentence-transformers, requests, python-dotenv, IPython, etc. If not, create one manually based on your code's imports.
+
+Step 3: Configure Your API Key
+For security, your Llama API key must be stored as an environment variable and not directly in your code.
+
+Create a .env file: In the root of the technical_blogger directory, create a new file named .env.
+
+Add your Llama API Key: Open the .env file and add your Llama API key in the following format:
+
+LLAMA_API_KEY="YOUR_LLAMA_API_KEY_HERE"
+Replace "YOUR_LLAMA_API_KEY_HERE" with your actual API key.
+
+Add .env to .gitignore: To prevent accidentally committing your API key, ensure .env is listed in your .gitignore file. If you don't have one, create it and add the line /.env.
+
+Step 4: Prepare Your Knowledge Base (Data Ingestion)
+This recipe uses an in-memory Qdrant database, meaning the knowledge base is built each time the script runs. You will need to provide your technical documentation for ingestion.
+
+Locate generate_blog function: Open the Technical_Blog_Generator.ipynb (or your main Python script if you converted it) and find the generate_blog function.
+
+Update ingest_data_into_qdrant call: Inside generate_blog, there's a section for data ingestion:
+
+Python
+
+# IMPORTANT: For in-memory Qdrant, you MUST ingest your data every time
+# the script runs or the client is initialized, as it's not persistent.
+# Replace this with your actual data loading and chunking.
+# Example placeholder data:
+example_data_chunks = [
+    # ... your example data ...
+]
+ingest_data_into_qdrant(client, MAIN_COLLECTION_NAME, embedding_model, example_data_chunks)
+Replace example_data_chunks with your actual code to load your technical documentation (e.g., from mdfiles_latest.txt, 3rd_party_integrations.txt, etc.), chunk it appropriately, and pass it to the ingest_data_into_qdrant function. This step defines the content that Llama will retrieve and use.
+
+Example (conceptual - adapt to your file loading logic):
+
+Python
+
+# Assuming your raw text files are in a 'cookbook_metadata' folder
+# and you have a function to read and chunk them.
+from your_data_loader_module import load_and_chunk_docs # You need to implement this
+
+all_your_technical_docs_chunks = []
+# Load from mdfiles_latest.txt, 3rd_party_integrations.txt, Getting_started_files.txt
+# and split into chunks suitable for embedding.
+# Example:
+# with open('cookbook_metadata/mdfiles_latest.txt', 'r') as f:
+#     content = f.read()
+#     all_your_technical_docs_chunks.extend(your_chunking_function(content))
+# ... repeat for other files ...
+
+ingest_data_into_qdrant(client, MAIN_COLLECTION_NAME, embedding_model, all_your_technical_docs_chunks)
+Step 5: Run the Notebook
+With your environment configured and data ingestion prepared, you can now open the Jupyter notebook and run the blog generator.
+
+Start Jupyter:
+
+Bash
+
+jupyter notebook
+Open the Notebook: In your browser, navigate to the technical_blogger folder and open Technical_Blog_Generator.ipynb.
+
+Run Cells: Execute each cell in the notebook sequentially. This will:
+
+Initialize the Llama API client.
+
+Set up the in-memory Qdrant database and ingest your provided knowledge base.
+
+Load helper functions for querying.
+
+Allow you to specify a blog topic.
+
+Trigger the RAG process to generate and display the blog post.
+
+Customization
+Knowledge Base: Expand your knowledge base by adding more technical documentation files. Remember to update the data ingestion logic in generate_blog (Step 4) to include these new sources.
+
+LLM Model: Experiment with different Llama models by changing the LLAMA_MODEL variable in the configuration.
+
+Prompt Engineering: Modify the system_prompt within the generate_blog function to control the tone, structure, depth, and specific requirements for your generated blog posts.
+
+RAG Parameters: Adjust top_k in the query_qdrant function to retrieve more or fewer relevant chunks. You can also experiment with different embedding models or reranking models.
+
+Output Format: Customize the output formatting if you need something other than Markdown.

+ 6 - 0
end-to-end-use-cases/technical_blogger/requirements.txt

@@ -0,0 +1,6 @@
+requests
+qdrant-client
+sentence-transformers
+IPython
+jupyter
+python-dotenv

+ 98 - 0
end-to-end-use-cases/technical_blogger/setup_qdrant_collection.py

@@ -0,0 +1,98 @@
+
+# qdrant_setup_partial.py
+from pathlib import Path
+from qdrant_client import QdrantClient, models
+from sentence_transformers import SentenceTransformer
+import uuid
+import re
+
+# Configuration
+QDRANT_URL = "https://754e68dd-c297-4ab2-9833-c81cbfbfb75c.eu-west-2-0.aws.cloud.qdrant.io:6333"
+QDRANT_API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3MiOiJtIn0.kRiEKHQ5s4KUWoYJqhQ29tbmbgfqFT2jAAfgrPTshSM"
+EMBEDDING_MODEL = 'all-MiniLM-L6-v2'
+
+# New files to process
+# IMPORTANT: Added the configuration for readme_blogs_latest here
+NEW_COLLECTIONS = [
+    {
+        "file_path": "/home/ubuntu/nilesh-workspace-backup-20250707/Blog_generation/internal-llama-cookbook/end-to-end-use-cases/technical_blogger/Blog_generation/cookbook_metadata/mdfiles_latest.txt",
+        "collection_name": "readme_blogs_latest"
+    },
+    {
+        "file_path": "/home/ubuntu/nilesh-workspace-backup-20250707/Blog_generation/internal-llama-cookbook/end-to-end-use-cases/technical_blogger/Blog_generation/cookbook_metadata/3rd_party_integrations.txt",
+        "collection_name": "3rd_party_integrations"
+    },
+    {
+        "file_path": "/home/ubuntu/nilesh-workspace-backup-20250707/Blog_generation/internal-llama-cookbook/end-to-end-use-cases/technical_blogger/Blog_generation/cookbook_metadata/Getting_started_files.txt",
+        "collection_name": "getting_started_files"
+    }
+]
+
+def markdown_splitter(text, max_chunk=800):
+    sections = re.split(r'(?=^#+ .*)', text, flags=re.MULTILINE)
+    chunks = []
+    current_chunk = []
+    
+    for section in sections:
+        if len(''.join(current_chunk)) + len(section) > max_chunk:
+            chunks.append(''.join(current_chunk))
+            current_chunk = [section]
+        else:
+            current_chunk.append(section)
+    
+    if current_chunk:
+        chunks.append(''.join(current_chunk))
+    
+    return [{"text": chunk, "header": f"section_{i}"} for i, chunk in enumerate(chunks)]
+
+def get_qdrant_client():
+    return QdrantClient(url=QDRANT_URL, api_key=QDRANT_API_KEY)
+
+def get_embedding_model():
+    return SentenceTransformer(EMBEDDING_MODEL)
+
+def process_file(config):
+    client = get_qdrant_client()
+    embedding_model = get_embedding_model()
+    
+    # Create collection if not exists
+    if not client.collection_exists(config["collection_name"]):
+        client.create_collection(
+            collection_name=config["collection_name"],
+            vectors_config=models.VectorParams(
+                size=384,
+                distance=models.Distance.COSINE
+            )
+        )
+    
+    # Process and store documents
+    try:
+        text = Path(config["file_path"]).read_text(encoding='utf-8')
+        chunks = markdown_splitter(text)
+        
+        batch_size = 100
+        for i in range(0, len(chunks), batch_size):
+            batch = chunks[i:i+batch_size]
+            points = []
+            for chunk in batch:
+                embedding = embedding_model.encode(chunk["text"]).tolist()
+                points.append(
+                    models.PointStruct(
+                        id=str(uuid.uuid4()),
+                        vector=embedding,
+                        payload=chunk
+                    )
+                )
+            client.upsert(collection_name=config["collection_name"], points=points)
+        
+        print(f"Processed {len(chunks)} chunks for {config['collection_name']}")
+    except FileNotFoundError:
+        print(f"Error: The file at {config['file_path']} was not found. Skipping collection setup.")
+
+def setup_all_collections():
+    for config in NEW_COLLECTIONS:
+        process_file(config)
+    print("All collections created and populated successfully!")
+
+if __name__ == "__main__":
+    setup_all_collections()