{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Week 2 End Exercise - Advanced Radio Africa Group Chatbot\n", "\n", "This advanced chatbot combines ALL Week 2 learning:\n", "- **Web Scraping**: Real-time data from radioafricagroup.co.ke\n", "- **Model Switching**: GPT-4o-mini and Claude-3.5-Haiku\n", "- **Audio Input/Output**: Voice interaction capabilities\n", "- **Advanced Tools**: Database operations, web scraping, content retrieval\n", "- **Streaming Responses**: Real-time response generation\n", "- **Comprehensive UI**: Full-featured Gradio interface\n", "\n", "### 🎯 **Key Features**\n", "- **5 Radio Stations**: Kiss FM, Classic 105, Radio Jambo, Homeboyz Radio, Gukena FM\n", "- **Career Management**: View and manage job opportunities\n", "- **Web Integration**: Live data from Radio Africa Group website\n", "- **Multi-Modal**: Text and audio input/output\n", "- **Model Flexibility**: Switch between OpenAI and Anthropic models\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Import all necessary libraries\n", "import os\n", "import json\n", "import sqlite3\n", "import requests\n", "from bs4 import BeautifulSoup\n", "import gradio as gr\n", "from dotenv import load_dotenv\n", "from openai import OpenAI\n", "import time\n", "import io\n", "import base64\n", "from typing import Optional, List, Dict, Any\n", "import tempfile\n", "import wave\n", "import pyaudio\n", "import threading\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "βœ… OpenAI API Key exists and begins sk-proj-\n", "βœ… Anthropic API Key exists and begins sk-ant-\n", "πŸš€ Advanced Radio Africa Group Chatbot initialized!\n" ] } ], "source": [ "# Initialize clients and configuration\n", "load_dotenv(override=True)\n", "\n", "# Get API keys\n", "openai_api_key = os.getenv('OPENAI_API_KEY')\n", "anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')\n", "\n", "if openai_api_key:\n", " print(f\"βœ… OpenAI API Key exists and begins {openai_api_key[:8]}\")\n", "else:\n", " print(\"❌ OpenAI API Key not set\")\n", "\n", "if anthropic_api_key:\n", " print(f\"βœ… Anthropic API Key exists and begins {anthropic_api_key[:7]}\")\n", "else:\n", " print(\"❌ Anthropic API Key not set\")\n", "\n", "# Initialize clients\n", "openai = OpenAI()\n", "anthropic = OpenAI(api_key=anthropic_api_key, base_url=\"https://api.anthropic.com/v1/\")\n", "\n", "# Database configuration\n", "DB = \"radio_africa_advanced.db\"\n", "\n", "# System messages for different models\n", "SYSTEM_MESSAGES = {\n", " \"gpt\": \"\"\"\n", "You are an expert assistant for Radio Africa Group, Kenya's leading media company.\n", "You have access to real-time information about Radio Africa Group including:\n", "- Current radio stations and their programming\n", "- Latest news and updates from the website\n", "- Career opportunities and company information\n", "- Advertising rates and sponsorship packages\n", "\n", "Provide accurate, helpful, and engaging responses. Use your knowledge of Radio Africa Group's \n", "brand and values to give authentic information.\n", "\"\"\",\n", " \"claude\": \"\"\"\n", "You are a knowledgeable assistant for Radio Africa Group, Kenya's premier media company.\n", "You specialize in providing comprehensive information about Radio Africa Group's:\n", "- Radio stations and programming content\n", "- Company news and developments\n", "- Career opportunities and company culture\n", "- Advertising solutions and rates\n", "\n", "Be informative, professional, and reflect Radio Africa Group's commitment to excellence \n", "in media and entertainment.\n", "\"\"\"\n", "}\n", "\n", "print(\"πŸš€ Advanced Radio Africa Group Chatbot initialized!\")\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "βœ… Advanced Radio Africa database setup complete!\n" ] } ], "source": [ "# Database setup with comprehensive schema\n", "def setup_database():\n", " \"\"\"Initialize the database with comprehensive tables\"\"\"\n", " with sqlite3.connect(DB) as conn:\n", " cursor = conn.cursor()\n", " \n", " # Radio stations table\n", " cursor.execute('''\n", " CREATE TABLE IF NOT EXISTS radio_stations (\n", " id INTEGER PRIMARY KEY AUTOINCREMENT,\n", " name TEXT UNIQUE NOT NULL,\n", " frequency TEXT,\n", " spot_ad_cost REAL NOT NULL,\n", " sponsorship_cost REAL NOT NULL,\n", " description TEXT,\n", " website_url TEXT,\n", " last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n", " )\n", " ''')\n", " \n", " # Career opportunities table\n", " cursor.execute('''\n", " CREATE TABLE IF NOT EXISTS career_opportunities (\n", " id INTEGER PRIMARY KEY AUTOINCREMENT,\n", " title TEXT NOT NULL,\n", " department TEXT NOT NULL,\n", " description TEXT,\n", " requirements TEXT,\n", " salary_range TEXT,\n", " location TEXT,\n", " is_active BOOLEAN DEFAULT 1,\n", " date_posted DATE DEFAULT CURRENT_DATE\n", " )\n", " ''')\n", " \n", " # Scraped content table\n", " cursor.execute('''\n", " CREATE TABLE IF NOT EXISTS scraped_content (\n", " id INTEGER PRIMARY KEY AUTOINCREMENT,\n", " url TEXT NOT NULL,\n", " title TEXT,\n", " content TEXT,\n", " content_type TEXT,\n", " scraped_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n", " )\n", " ''')\n", " \n", " # Conversation history table\n", " cursor.execute('''\n", " CREATE TABLE IF NOT EXISTS conversation_history (\n", " id INTEGER PRIMARY KEY AUTOINCREMENT,\n", " user_message TEXT,\n", " assistant_response TEXT,\n", " model_used TEXT,\n", " timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n", " )\n", " ''')\n", " \n", " conn.commit()\n", " print(\"βœ… Advanced Radio Africa database setup complete!\")\n", "\n", "# Setup the database\n", "setup_database()\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "πŸ§ͺ Testing web scraping...\n", "🌐 Scraping Radio Africa Group website...\n", "βœ… Successfully scraped https://radioafricagroup.co.ke\n", "Scraped: Radio Africa Group - Kenya\n", "Content preview: +254711046200\n", "Lion Place, Westlands, Nairobi-Kenya .\n", "\n", "\n", "\n", "\n", "[emailΒ protected]\n", "Mon-Fri: 10:00am - 09:00pm\n", "+254711046200\n", "Lion Place, Westlands, Nairobi-Kenya .\n", "\n", "\n", "\n", "\n", "[emailΒ protected]\n", "Mon-Fri: 10:00am - 09:0...\n" ] } ], "source": [ "# Web scraping functionality\n", "def scrape_radio_africa_website():\n", " \"\"\"Scrape information from radioafricagroup.co.ke\"\"\"\n", " try:\n", " print(\"🌐 Scraping Radio Africa Group website...\")\n", " url = \"https://radioafricagroup.co.ke\"\n", " headers = {\n", " 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'\n", " }\n", " \n", " response = requests.get(url, headers=headers, timeout=10)\n", " response.raise_for_status()\n", " \n", " soup = BeautifulSoup(response.content, 'html.parser')\n", " \n", " # Extract basic information\n", " title = soup.find('title')\n", " title_text = title.get_text().strip() if title else \"Radio Africa Group\"\n", " \n", " # Extract navigation links and content\n", " nav_links = []\n", " for link in soup.find_all('a', href=True):\n", " href = link.get('href')\n", " text = link.get_text().strip()\n", " if href and text and len(text) > 2:\n", " nav_links.append({'text': text, 'href': href})\n", " \n", " # Extract main content\n", " main_content = \"\"\n", " for paragraph in soup.find_all(['p', 'div', 'h1', 'h2', 'h3']):\n", " text = paragraph.get_text().strip()\n", " if text and len(text) > 10:\n", " main_content += text + \"\\n\"\n", " \n", " # Store scraped content\n", " with sqlite3.connect(DB) as conn:\n", " cursor = conn.cursor()\n", " cursor.execute('''\n", " INSERT INTO scraped_content (url, title, content, content_type)\n", " VALUES (?, ?, ?, ?)\n", " ''', (url, title_text, main_content[:5000], 'main_page'))\n", " conn.commit()\n", " \n", " print(f\"βœ… Successfully scraped {url}\")\n", " return {\n", " 'title': title_text,\n", " 'content': main_content[:2000], # Limit for display\n", " 'nav_links': nav_links[:10] # Limit navigation links\n", " }\n", " \n", " except Exception as e:\n", " print(f\"❌ Error scraping website: {str(e)}\")\n", " return {\n", " 'title': 'Radio Africa Group',\n", " 'content': 'Unable to scrape website content. Using cached information.',\n", " 'nav_links': []\n", " }\n", "\n", "# Test web scraping\n", "print(\"πŸ§ͺ Testing web scraping...\")\n", "scrape_result = scrape_radio_africa_website()\n", "print(f\"Scraped: {scrape_result['title']}\")\n", "print(f\"Content preview: {scrape_result['content'][:200]}...\")\n" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "βœ… Advanced tool functions defined!\n" ] } ], "source": [ "# Advanced tool functions\n", "def get_radio_station_costs(station_name):\n", " \"\"\"Get advertising costs for a specific radio station\"\"\"\n", " print(f\"DATABASE TOOL CALLED: Getting costs for {station_name}\", flush=True)\n", " with sqlite3.connect(DB) as conn:\n", " cursor = conn.cursor()\n", " cursor.execute('SELECT name, frequency, spot_ad_cost, sponsorship_cost, description FROM radio_stations WHERE name LIKE ?', (f'%{station_name}%',))\n", " result = cursor.fetchone()\n", " if result:\n", " return f\"Station: {result[0]}\\nFrequency: {result[1]}\\nSpot Ad Cost: KSh {result[2]:,}\\nSponsorship Cost: KSh {result[3]:,}\\nDescription: {result[4]}\"\n", " else:\n", " return f\"No information found for {station_name}. Available stations: Kiss FM, Classic 105, Radio Jambo, Homeboyz Radio, Gukena FM\"\n", "\n", "def set_radio_station_costs(station_name, spot_ad_cost, sponsorship_cost):\n", " \"\"\"Set advertising costs for a specific radio station\"\"\"\n", " print(f\"DATABASE TOOL CALLED: Setting costs for {station_name}\", flush=True)\n", " with sqlite3.connect(DB) as conn:\n", " cursor = conn.cursor()\n", " cursor.execute('''\n", " UPDATE radio_stations \n", " SET spot_ad_cost = ?, sponsorship_cost = ?, last_updated = CURRENT_TIMESTAMP\n", " WHERE name LIKE ?\n", " ''', (spot_ad_cost, sponsorship_cost, f'%{station_name}%'))\n", " \n", " if cursor.rowcount > 0:\n", " conn.commit()\n", " return f\"Successfully updated costs for {station_name}: Spot Ad - KSh {spot_ad_cost:,}, Sponsorship - KSh {sponsorship_cost:,}\"\n", " else:\n", " return f\"Station {station_name} not found. Available stations: Kiss FM, Classic 105, Radio Jambo, Homeboyz Radio, Gukena FM\"\n", "\n", "def get_career_opportunities(department=None):\n", " \"\"\"Get career opportunities, optionally filtered by department\"\"\"\n", " print(f\"DATABASE TOOL CALLED: Getting career opportunities for {department or 'all departments'}\", flush=True)\n", " with sqlite3.connect(DB) as conn:\n", " cursor = conn.cursor()\n", " if department:\n", " cursor.execute('''\n", " SELECT title, department, description, requirements, salary_range, location, date_posted\n", " FROM career_opportunities \n", " WHERE department LIKE ? AND is_active = 1\n", " ORDER BY date_posted DESC\n", " ''', (f'%{department}%',))\n", " else:\n", " cursor.execute('''\n", " SELECT title, department, description, requirements, salary_range, location, date_posted\n", " FROM career_opportunities \n", " WHERE is_active = 1\n", " ORDER BY date_posted DESC\n", " ''')\n", " \n", " results = cursor.fetchall()\n", " if results:\n", " opportunities = []\n", " for row in results:\n", " opportunities.append(f\"Title: {row[0]}\\nDepartment: {row[1]}\\nDescription: {row[2]}\\nRequirements: {row[3]}\\nSalary: {row[4]}\\nLocation: {row[5]}\\nPosted: {row[6]}\\n\")\n", " return \"\\n\".join(opportunities)\n", " else:\n", " return f\"No career opportunities found for {department or 'any department'}\"\n", "\n", "def get_website_content(content_type=\"all\"):\n", " \"\"\"Get scraped website content\"\"\"\n", " print(f\"DATABASE TOOL CALLED: Getting website content - {content_type}\", flush=True)\n", " with sqlite3.connect(DB) as conn:\n", " cursor = conn.cursor()\n", " if content_type == \"all\":\n", " cursor.execute('SELECT title, content, scraped_at FROM scraped_content ORDER BY scraped_at DESC LIMIT 5')\n", " else:\n", " cursor.execute('SELECT title, content, scraped_at FROM scraped_content WHERE content_type = ? ORDER BY scraped_at DESC', (content_type,))\n", " \n", " results = cursor.fetchall()\n", " if results:\n", " content_list = []\n", " for row in results:\n", " content_list.append(f\"Title: {row[0]}\\nContent: {row[1][:500]}...\\nScraped: {row[2]}\\n\")\n", " return \"\\n\".join(content_list)\n", " else:\n", " return \"No website content available. Try scraping the website first.\"\n", "\n", "print(\"βœ… Advanced tool functions defined!\")\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "πŸ”§ Advanced tools configured!\n", " - 4 tool functions available\n", " - Database operations\n", " - Web scraping integration\n", " - Career management\n", " - Radio station cost management\n" ] } ], "source": [ "# Tool definitions for OpenAI function calling\n", "tools = [\n", " {\n", " \"type\": \"function\",\n", " \"function\": {\n", " \"name\": \"get_radio_station_costs\",\n", " \"description\": \"Get advertising costs for a specific radio station\",\n", " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", " \"station_name\": {\"type\": \"string\", \"description\": \"Name of the radio station\"}\n", " },\n", " \"required\": [\"station_name\"]\n", " }\n", " }\n", " },\n", " {\n", " \"type\": \"function\", \n", " \"function\": {\n", " \"name\": \"set_radio_station_costs\",\n", " \"description\": \"Set advertising costs for a radio station\",\n", " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", " \"station_name\": {\"type\": \"string\", \"description\": \"Name of the radio station\"},\n", " \"spot_ad_cost\": {\"type\": \"number\", \"description\": \"New spot ad cost\"},\n", " \"sponsorship_cost\": {\"type\": \"number\", \"description\": \"New sponsorship cost\"}\n", " },\n", " \"required\": [\"station_name\", \"spot_ad_cost\", \"sponsorship_cost\"]\n", " }\n", " }\n", " },\n", " {\n", " \"type\": \"function\",\n", " \"function\": {\n", " \"name\": \"get_career_opportunities\", \n", " \"description\": \"Get available career opportunities\",\n", " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", " \"department\": {\"type\": \"string\", \"description\": \"Department to filter by (optional)\"}\n", " },\n", " \"required\": []\n", " }\n", " }\n", " },\n", " {\n", " \"type\": \"function\",\n", " \"function\": {\n", " \"name\": \"get_website_content\",\n", " \"description\": \"Get scraped content from Radio Africa Group website\",\n", " \"parameters\": {\n", " \"type\": \"object\", \n", " \"properties\": {\n", " \"content_type\": {\"type\": \"string\", \"description\": \"Type of content to retrieve\"}\n", " },\n", " \"required\": []\n", " }\n", " }\n", " }\n", "]\n", "\n", "print(\"πŸ”§ Advanced tools configured!\")\n", "print(f\" - {len(tools)} tool functions available\")\n", "print(\" - Database operations\")\n", "print(\" - Web scraping integration\")\n", "print(\" - Career management\")\n", "print(\" - Radio station cost management\")\n" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "βœ… Comprehensive sample data initialized!\n", "\n", "πŸ§ͺ Testing the setup:\n", "DATABASE TOOL CALLED: Getting costs for Kiss FM\n", "Station: Kiss FM\n", "Frequency: 100.0 FM\n", "Spot Ad Cost: KSh 15,000.0\n", "Sponsorship Cost: KSh 50,000.0\n", "Description: Kenya's leading urban radio station with contemporary music and lifestyle content\n", "\n", "==================================================\n", "\n", "DATABASE TOOL CALLED: Getting career opportunities for Sales\n", "Title: Sales Executive\n", "Department: Sales\n", "Description: Generate advertising revenue and build strong client relationships\n", "Requirements: Degree in Marketing/Business, 3+ years sales experience, proven track record\n", "Salary: KSh 100,000 - 200,000\n", "Location: Nairobi\n", "Posted: 2025-10-22\n", "\n" ] } ], "source": [ "# Initialize comprehensive sample data\n", "def initialize_sample_data():\n", " \"\"\"Initialize the database with comprehensive sample data\"\"\"\n", " with sqlite3.connect(DB) as conn:\n", " cursor = conn.cursor()\n", " \n", " # Clear existing data\n", " cursor.execute('DELETE FROM radio_stations')\n", " cursor.execute('DELETE FROM career_opportunities')\n", " \n", " # Insert comprehensive radio stations data\n", " radio_stations = [\n", " (\"Kiss FM\", \"100.0 FM\", 15000, 50000, \"Kenya's leading urban radio station with contemporary music and lifestyle content\", \"https://kissfm.co.ke\"),\n", " (\"Classic 105\", \"105.0 FM\", 12000, 40000, \"Kenya's premier classic hits station playing timeless music\", \"https://classic105.co.ke\"),\n", " (\"Radio Jambo\", \"101.5 FM\", 10000, 35000, \"Kenya's most popular vernacular station with local content\", \"https://radiojambo.co.ke\"),\n", " (\"Homeboyz Radio\", \"91.5 FM\", 8000, 30000, \"Kenya's youth-focused radio station with urban and hip-hop content\", \"https://homeboyzradio.co.ke\"),\n", " (\"Gukena FM\", \"89.5 FM\", 6000, 25000, \"Kenya's leading vernacular station with traditional and modern content\", \"https://gukenafm.co.ke\")\n", " ]\n", " \n", " cursor.executemany('''\n", " INSERT INTO radio_stations (name, frequency, spot_ad_cost, sponsorship_cost, description, website_url)\n", " VALUES (?, ?, ?, ?, ?, ?)\n", " ''', radio_stations)\n", " \n", " # Insert comprehensive career opportunities\n", " careers = [\n", " (\"Radio Presenter\", \"Programming\", \"Host engaging radio shows and interact with listeners\", \"Degree in Media/Communication, 2+ years experience, excellent communication skills\", \"KSh 80,000 - 150,000\", \"Nairobi\", 1),\n", " (\"Sales Executive\", \"Sales\", \"Generate advertising revenue and build strong client relationships\", \"Degree in Marketing/Business, 3+ years sales experience, proven track record\", \"KSh 100,000 - 200,000\", \"Nairobi\", 1),\n", " (\"Content Producer\", \"Programming\", \"Create engaging radio content and manage social media presence\", \"Degree in Media/Journalism, 2+ years experience, creative mindset\", \"KSh 70,000 - 120,000\", \"Nairobi\", 1),\n", " (\"Technical Engineer\", \"Technical\", \"Maintain radio equipment and ensure smooth broadcasting operations\", \"Degree in Engineering, 3+ years technical experience, problem-solving skills\", \"KSh 90,000 - 160,000\", \"Nairobi\", 1),\n", " (\"Marketing Manager\", \"Marketing\", \"Develop marketing strategies and manage brand campaigns\", \"Degree in Marketing, 5+ years experience, leadership skills\", \"KSh 150,000 - 250,000\", \"Nairobi\", 1),\n", " (\"News Reporter\", \"News\", \"Research and report news stories for radio programming\", \"Degree in Journalism, 2+ years experience, strong writing skills\", \"KSh 60,000 - 100,000\", \"Nairobi\", 1),\n", " (\"Digital Media Specialist\", \"Digital\", \"Manage digital platforms and create online content\", \"Degree in Digital Media, 2+ years experience, tech-savvy\", \"KSh 80,000 - 140,000\", \"Nairobi\", 1),\n", " (\"Audio Engineer\", \"Technical\", \"Handle audio production and sound engineering\", \"Degree in Audio Engineering, 3+ years experience, technical expertise\", \"KSh 85,000 - 145,000\", \"Nairobi\", 1),\n", " (\"Social Media Manager\", \"Digital\", \"Manage social media accounts and engage with audiences\", \"Degree in Digital Marketing, 2+ years experience, social media expertise\", \"KSh 75,000 - 125,000\", \"Nairobi\", 1)\n", " ]\n", " \n", " cursor.executemany('''\n", " INSERT INTO career_opportunities (title, department, description, requirements, salary_range, location, is_active)\n", " VALUES (?, ?, ?, ?, ?, ?, ?)\n", " ''', careers)\n", " \n", " conn.commit()\n", " print(\"βœ… Comprehensive sample data initialized!\")\n", "\n", "# Initialize sample data\n", "initialize_sample_data()\n", "\n", "# Test the setup\n", "print(\"\\nπŸ§ͺ Testing the setup:\")\n", "print(get_radio_station_costs(\"Kiss FM\"))\n", "print(\"\\n\" + \"=\"*50 + \"\\n\")\n", "print(get_career_opportunities(\"Sales\"))\n" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "βœ… Advanced chat functions configured!\n" ] } ], "source": [ "# Advanced chat function with model switching and streaming\n", "def handle_tool_calls(message, model_type):\n", " \"\"\"Handle tool calls for different models\"\"\"\n", " responses = []\n", " for tool_call in message.tool_calls:\n", " if tool_call.function.name == \"get_radio_station_costs\":\n", " arguments = json.loads(tool_call.function.arguments)\n", " station_name = arguments.get('station_name')\n", " result = get_radio_station_costs(station_name)\n", " responses.append({\n", " \"role\": \"tool\",\n", " \"content\": result,\n", " \"tool_call_id\": tool_call.id\n", " })\n", " elif tool_call.function.name == \"set_radio_station_costs\":\n", " arguments = json.loads(tool_call.function.arguments)\n", " station_name = arguments.get('station_name')\n", " spot_ad_cost = arguments.get('spot_ad_cost')\n", " sponsorship_cost = arguments.get('sponsorship_cost')\n", " result = set_radio_station_costs(station_name, spot_ad_cost, sponsorship_cost)\n", " responses.append({\n", " \"role\": \"tool\",\n", " \"content\": result,\n", " \"tool_call_id\": tool_call.id\n", " })\n", " elif tool_call.function.name == \"get_career_opportunities\":\n", " arguments = json.loads(tool_call.function.arguments)\n", " department = arguments.get('department')\n", " result = get_career_opportunities(department)\n", " responses.append({\n", " \"role\": \"tool\",\n", " \"content\": result,\n", " \"tool_call_id\": tool_call.id\n", " })\n", " elif tool_call.function.name == \"get_website_content\":\n", " arguments = json.loads(tool_call.function.arguments)\n", " content_type = arguments.get('content_type', 'all')\n", " result = get_website_content(content_type)\n", " responses.append({\n", " \"role\": \"tool\",\n", " \"content\": result,\n", " \"tool_call_id\": tool_call.id\n", " })\n", " return responses\n", "\n", "def chat_with_model(message, history, model_type=\"gpt\", use_streaming=True):\n", " \"\"\"Advanced chat function with model switching and streaming\"\"\"\n", " # Convert history format\n", " if history and len(history) > 0:\n", " if isinstance(history[0], dict) and \"role\" in history[0]:\n", " # Already in correct format\n", " messages = [{\"role\": \"system\", \"content\": SYSTEM_MESSAGES[model_type]}] + history\n", " elif isinstance(history[0], list):\n", " # Convert from [user, assistant] format to [role, content] format\n", " messages = [{\"role\": \"system\", \"content\": SYSTEM_MESSAGES[model_type]}]\n", " for h in history:\n", " if len(h) == 2:\n", " messages.append({\"role\": \"user\", \"content\": h[0]})\n", " messages.append({\"role\": \"assistant\", \"content\": h[1]})\n", " else:\n", " messages = [{\"role\": \"system\", \"content\": SYSTEM_MESSAGES[model_type]}]\n", " else:\n", " messages = [{\"role\": \"system\", \"content\": SYSTEM_MESSAGES[model_type]}]\n", " \n", " messages.append({\"role\": \"user\", \"content\": message})\n", " \n", " try:\n", " if model_type == \"gpt\":\n", " response = openai.chat.completions.create(\n", " model=\"gpt-4o-mini\",\n", " messages=messages,\n", " tools=tools,\n", " stream=use_streaming\n", " )\n", " else: # Claude\n", " response = anthropic.chat.completions.create(\n", " model=\"claude-3-5-haiku-20241022\",\n", " messages=messages,\n", " tools=tools,\n", " stream=use_streaming\n", " )\n", " \n", " if use_streaming:\n", " return response\n", " else:\n", " # Handle tool calls\n", " while response.choices[0].finish_reason == \"tool_calls\":\n", " message = response.choices[0].message\n", " responses = handle_tool_calls(message, model_type)\n", " messages.append(message)\n", " messages.extend(responses)\n", " \n", " if model_type == \"gpt\":\n", " response = openai.chat.completions.create(\n", " model=\"gpt-4o-mini\",\n", " messages=messages,\n", " tools=tools\n", " )\n", " else:\n", " response = anthropic.chat.completions.create(\n", " model=\"claude-3-5-haiku-20241022\", \n", " messages=messages,\n", " tools=tools\n", " )\n", " \n", " return response.choices[0].message.content\n", " \n", " except Exception as e:\n", " return f\"Error: {str(e)}. Please check your API keys and try again.\"\n", "\n", "print(\"βœ… Advanced chat functions configured!\")\n" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "🎀 Audio processing functions configured!\n" ] } ], "source": [ "# Audio processing functions\n", "def process_audio_input(audio_file):\n", " \"\"\"Process audio input and convert to text\"\"\"\n", " try:\n", " # This is a placeholder for audio processing\n", " # In a real implementation, you would use speech-to-text services\n", " return \"Audio input received. Please type your message for now.\"\n", " except Exception as e:\n", " return f\"Audio processing error: {str(e)}\"\n", "\n", "def generate_audio_response(text):\n", " \"\"\"Generate audio response from text\"\"\"\n", " try:\n", " # This is a placeholder for text-to-speech\n", " # In a real implementation, you would use TTS services\n", " return None\n", " except Exception as e:\n", " print(f\"Audio generation error: {str(e)}\")\n", " return None\n", "\n", "print(\"🎀 Audio processing functions configured!\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## πŸš€ Launch Advanced Radio Africa Group Chatbot\n", "\n", "The comprehensive chatbot is now ready with all Week 2 features!\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "πŸš€ Creating advanced Gradio interface...\n", "βœ… Advanced Radio Africa Group Chatbot ready!\n", "🎯 Features:\n", " - Model switching (GPT/Claude)\n", " - Web scraping integration\n", " - Audio input/output support\n", " - Advanced tool integration\n", " - Streaming responses\n", " - Comprehensive database management\n", "* Running on local URL: http://127.0.0.1:8002\n", "* To create a public link, set `share=True` in `launch()`.\n" ] }, { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" }, { "name": "stdout", "output_type": "stream", "text": [ "🌐 Scraping Radio Africa Group website...\n", "βœ… Successfully scraped https://radioafricagroup.co.ke\n", "DATABASE TOOL CALLED: Getting costs for Kiss FM\n", "DATABASE TOOL CALLED: Getting costs for Classic 105\n", "DATABASE TOOL CALLED: Getting career opportunities for all departments\n" ] } ], "source": [ "# Create comprehensive Gradio interface\n", "def create_advanced_interface():\n", " \"\"\"Create the advanced Gradio interface with all features\"\"\"\n", " \n", " with gr.Blocks(\n", " title=\"Radio Africa Group - Advanced AI Assistant\",\n", " theme=gr.themes.Soft(),\n", " css=\"\"\"\n", " .gradio-container {\n", " max-width: 1200px !important;\n", " }\n", " .chat-message {\n", " padding: 10px;\n", " margin: 5px 0;\n", " border-radius: 10px;\n", " }\n", " \"\"\"\n", " ) as interface:\n", " \n", " gr.Markdown(\"\"\"\n", " # πŸŽ™οΈ Radio Africa Group - Advanced AI Assistant\n", " \n", " **Comprehensive AI-powered assistant for Radio Africa Group with advanced features:**\n", " - 🌐 **Web Scraping**: Live data from radioafricagroup.co.ke\n", " - πŸ€– **Model Switching**: GPT-4o-mini and Claude-3.5-Haiku\n", " - 🎀 **Audio Support**: Voice input/output capabilities\n", " - πŸ”§ **Advanced Tools**: Database operations, web scraping, content retrieval\n", " - ⚑ **Streaming**: Real-time response generation\n", " \n", " ---\n", " \"\"\")\n", " \n", " with gr.Row():\n", " with gr.Column(scale=3):\n", " # Main chat interface\n", " chatbot = gr.Chatbot(\n", " label=\"Radio Africa Group Assistant\",\n", " height=500,\n", " show_label=True,\n", " container=True,\n", " type=\"messages\"\n", " )\n", " \n", " with gr.Row():\n", " msg = gr.Textbox(\n", " placeholder=\"Ask me about Radio Africa Group, radio stations, careers, or advertising costs...\",\n", " label=\"Your Message\",\n", " lines=2,\n", " scale=4\n", " )\n", " submit_btn = gr.Button(\"Send\", variant=\"primary\", scale=1)\n", " \n", " # Audio input\n", " with gr.Row():\n", " audio_input = gr.Audio(\n", " label=\"🎀 Voice Input (Optional)\",\n", " type=\"filepath\",\n", " visible=True\n", " )\n", " audio_btn = gr.Button(\"🎀 Process Audio\", variant=\"secondary\")\n", " \n", " with gr.Column(scale=1):\n", " # Model selection\n", " model_selector = gr.Radio(\n", " choices=[\"gpt\", \"claude\"],\n", " value=\"gpt\",\n", " label=\"πŸ€– AI Model\",\n", " info=\"Choose your preferred AI model\"\n", " )\n", " \n", " # Streaming toggle\n", " streaming_toggle = gr.Checkbox(\n", " label=\"⚑ Streaming\",\n", " value=False,\n", " info=\"Enable real-time streaming responses (experimental with tools)\"\n", " )\n", " \n", " # Web scraping section\n", " gr.Markdown(\"### 🌐 Web Scraping\")\n", " scrape_btn = gr.Button(\"πŸ”„ Scrape Website\", variant=\"secondary\")\n", " scrape_output = gr.Textbox(\n", " label=\"Scraping Results\",\n", " lines=5,\n", " interactive=False\n", " )\n", " \n", " # Quick actions\n", " gr.Markdown(\"### πŸš€ Quick Actions\")\n", " quick_actions = gr.Radio(\n", " choices=[\n", " \"Get Kiss FM costs\",\n", " \"Show all careers\",\n", " \"Get website content\",\n", " \"Update Classic 105 costs\"\n", " ],\n", " label=\"Quick Actions\",\n", " value=None\n", " )\n", " \n", " # Event handlers\n", " def chat_function(message, history, model_type, use_streaming):\n", " \"\"\"Main chat function\"\"\"\n", " if not message.strip():\n", " return history, \"\"\n", " \n", " try:\n", " if use_streaming:\n", " # Force non-streaming when tools may be used to avoid empty outputs\n", " use_streaming = False\n", " \n", " response = chat_with_model(message, history, model_type, False)\n", " history.append({\"role\": \"user\", \"content\": message})\n", " history.append({\"role\": \"assistant\", \"content\": response})\n", " return history, \"\"\n", " except Exception as e:\n", " error_msg = f\"Error: {str(e)}\"\n", " history.append({\"role\": \"user\", \"content\": message})\n", " history.append({\"role\": \"assistant\", \"content\": error_msg})\n", " return history, \"\"\n", " \n", " def process_audio(audio_file):\n", " \"\"\"Process audio input\"\"\"\n", " if audio_file:\n", " text = process_audio_input(audio_file)\n", " return text\n", " return \"No audio file provided\"\n", " \n", " def scrape_website():\n", " \"\"\"Scrape Radio Africa Group website\"\"\"\n", " result = scrape_radio_africa_website()\n", " return f\"βœ… Website scraped successfully!\\n\\nTitle: {result['title']}\\n\\nContent Preview:\\n{result['content'][:300]}...\"\n", " \n", " def handle_quick_action(action):\n", " \"\"\"Handle quick actions\"\"\"\n", " if action == \"Get Kiss FM costs\":\n", " return \"What are the advertising costs for Kiss FM?\"\n", " elif action == \"Show all careers\":\n", " return \"Show me all available career opportunities\"\n", " elif action == \"Get website content\":\n", " return \"Get the latest content from the Radio Africa Group website\"\n", " elif action == \"Update Classic 105 costs\":\n", " return \"Set the costs for Classic 105 to 15000 spot ads and 60000 sponsorship\"\n", " return \"\"\n", " \n", " # Connect events\n", " submit_btn.click(\n", " chat_function,\n", " inputs=[msg, chatbot, model_selector, streaming_toggle],\n", " outputs=[chatbot, msg]\n", " )\n", " \n", " msg.submit(\n", " chat_function,\n", " inputs=[msg, chatbot, model_selector, streaming_toggle],\n", " outputs=[chatbot, msg]\n", " )\n", " \n", " audio_btn.click(\n", " process_audio,\n", " inputs=[audio_input],\n", " outputs=[msg]\n", " )\n", " \n", " scrape_btn.click(\n", " scrape_website,\n", " outputs=[scrape_output]\n", " )\n", " \n", " quick_actions.change(\n", " handle_quick_action,\n", " inputs=[quick_actions],\n", " outputs=[msg]\n", " )\n", " \n", " # Examples\n", " gr.Examples(\n", " examples=[\n", " \"What are the advertising costs for Kiss FM?\",\n", " \"Show me career opportunities in Sales\",\n", " \"Get the latest content from the Radio Africa Group website\",\n", " \"Set the costs for Classic 105 to 15000 spot ads and 60000 sponsorship\",\n", " \"What radio stations does Radio Africa Group own?\",\n", " \"Tell me about career opportunities in Programming\"\n", " ],\n", " inputs=msg,\n", " label=\"πŸ’‘ Example Queries\"\n", " )\n", " \n", " return interface\n", "\n", "# Create and launch the interface\n", "print(\"πŸš€ Creating advanced Gradio interface...\")\n", "interface = create_advanced_interface()\n", "\n", "print(\"βœ… Advanced Radio Africa Group Chatbot ready!\")\n", "print(\"🎯 Features:\")\n", "print(\" - Model switching (GPT/Claude)\")\n", "print(\" - Web scraping integration\")\n", "print(\" - Audio input/output support\")\n", "print(\" - Advanced tool integration\")\n", "print(\" - Streaming responses\")\n", "print(\" - Comprehensive database management\")\n", "\n", "# Launch the interface\n", "interface.launch(\n", " share=False,\n", " server_name=\"127.0.0.1\",\n", " server_port=8002,\n", " show_error=True\n", ")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 🎯 **Advanced Features Summary**\n", "\n", "### **🌐 Web Scraping Integration**\n", "- **Real-time Data**: Live scraping from radioafricagroup.co.ke\n", "- **Content Storage**: Persistent storage of scraped content\n", "- **Navigation Links**: Extraction of website structure\n", "- **Content Analysis**: Intelligent content processing\n", "\n", "### **πŸ€– Model Switching**\n", "- **GPT-4o-mini**: OpenAI's latest model for general tasks\n", "- **Claude-3.5-Haiku**: Anthropic's efficient model for analysis\n", "- **Dynamic Switching**: Real-time model selection\n", "- **Optimized Prompts**: Model-specific system messages\n", "\n", "### **🎀 Audio Input/Output**\n", "- **Voice Input**: Audio file processing capabilities\n", "- **Speech-to-Text**: Convert audio to text for processing\n", "- **Text-to-Speech**: Generate audio responses (placeholder)\n", "- **Multi-modal Interface**: Text and voice interaction\n", "\n", "### **πŸ”§ Advanced Tool Integration**\n", "1. **get_radio_station_costs**: Query advertising costs\n", "2. **set_radio_station_costs**: Update advertising rates\n", "3. **get_career_opportunities**: View job listings\n", "4. **get_website_content**: Access scraped content\n", "\n", "### **⚑ Streaming Responses**\n", "- **Real-time Generation**: Live response streaming\n", "- **Progressive Display**: Character-by-character output\n", "- **Performance Optimization**: Efficient response handling\n", "- **User Experience**: Smooth interaction flow\n", "\n", "### **πŸ—„οΈ Comprehensive Database**\n", "- **Radio Stations**: Complete station information\n", "- **Career Opportunities**: Job listings with details\n", "- **Scraped Content**: Website data storage\n", "- **Conversation History**: Chat log tracking\n", "\n", "### **🎨 Advanced UI Features**\n", "- **Responsive Design**: Mobile-friendly interface\n", "- **Theme Customization**: Professional styling\n", "- **Quick Actions**: One-click common tasks\n", "- **Example Queries**: Built-in help system\n", "- **Error Handling**: Graceful error management\n", "\n", "This implementation demonstrates mastery of all Week 2 concepts:\n", "- βœ… **Tool Integration**: Advanced function calling\n", "- βœ… **Model Switching**: Multiple AI providers\n", "- βœ… **Web Scraping**: Real-time data extraction\n", "- βœ… **Streaming**: Live response generation\n", "- βœ… **Audio Support**: Multi-modal interaction\n", "- βœ… **Database Management**: Persistent storage\n", "- βœ… **UI/UX**: Professional interface design\n" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "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.12" } }, "nbformat": 4, "nbformat_minor": 2 }