import gradio as gr import requests from bs4 import BeautifulSoup import json from urllib.parse import quote_plus import time import logging # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) def search_knowledge_base(issue): """ Search the knowledge base for solutions related to the provided issue. Args: issue (str): The technical issue to search for Returns: str: Solution steps or message if no solution found """ try: issue = issue.lower() if "wifi" in issue: return "1. Check if your router is powered on\n2. Restart your router\n3. Try connecting again\n4. If problem persists, contact your ISP" elif "screen" in issue: return "1. Adjust display cable connections\n2. Update graphics drivers\n3. Restart the system\n4. Try a different monitor if available" elif "sound" in issue or "audio" in issue: return "1. Check volume settings\n2. Verify audio output device selection\n3. Update audio drivers\n4. Test with headphones" return "No predefined solution found in the knowledge base. Please try our web search tool for more information." except Exception as e: logger.error(f"Error in knowledge base search: {str(e)}") return f"Error searching knowledge base: {str(e)}" def search_web_duckduckgo(query): """ Perform actual web search using DuckDuckGo API. Args: query (str): The search query Returns: str: Formatted search results """ try: # DuckDuckGo Instant Answer API url = f"https://api.duckduckgo.com/?q={quote_plus(query)}&format=json&no_html=1&skip_disambig=1" response = requests.get(url, timeout=10) response.raise_for_status() data = response.json() results = [] # Get instant answer if available if data.get('AbstractText'): results.append(f"**Summary:** {data['AbstractText']}") # Get related topics if data.get('RelatedTopics'): results.append("\n**Related Information:**") for i, topic in enumerate(data['RelatedTopics'][:3], 1): if isinstance(topic, dict) and topic.get('Text'): results.append(f"{i}. {topic['Text']}") # Get definition if available if data.get('Definition'): results.append(f"\n**Definition:** {data['Definition']}") if results: return "\n".join(results) else: return f"Search completed for '{query}' but no detailed results available. Try a more specific query." except requests.RequestException as e: logger.error(f"Web search API error: {str(e)}") return f"Error performing web search: {str(e)}" except Exception as e: logger.error(f"Unexpected web search error: {str(e)}") return f"Unexpected error: {str(e)}" def search_web_scraper(query): """ Alternative web search using web scraping (backup method). Args: query (str): The search query Returns: str: Formatted search results """ try: # Use DuckDuckGo HTML search as backup search_url = f"https://duckduckgo.com/html/?q={quote_plus(query)}" headers = { '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' } response = requests.get(search_url, headers=headers, timeout=10) response.raise_for_status() soup = BeautifulSoup(response.content, 'html.parser') # Extract search results results = [] result_links = soup.find_all('a', class_='result__a')[:5] # Get top 5 results for i, link in enumerate(result_links, 1): title = link.get_text(strip=True) if title: results.append(f"{i}. {title}") if results: return f"**Search Results for '{query}':**\n" + "\n".join(results) else: return f"No results found for '{query}'. Try different keywords." except Exception as e: logger.error(f"Web scraping error: {str(e)}") return f"Error in backup search: {str(e)}" def search_web(query): """ Main web search function that tries multiple methods. Args: query (str): The search query Returns: str: Formatted search results """ try: if not query.strip(): return "Please enter a search query." # Try DuckDuckGo API first result = search_web_duckduckgo(query) # If API fails, try scraping method if "Error" in result: logger.info("API method failed, trying scraping method...") result = search_web_scraper(query) return result except Exception as e: logger.error(f"Error in main web search: {str(e)}") return f"Error processing your search: {str(e)}" def format_response(raw_steps): """ Format the raw steps into a numbered list. Args: raw_steps (str): Raw text steps separated by periods Returns: str: Formatted numbered list of steps """ try: if not raw_steps.strip(): return "Please enter some text to format." # Handle multiple delimiters steps = re.split(r'[.,;]\s*', raw_steps) steps = [step.strip() for step in steps if step.strip()] steps = [f"{i+1}. {step}" for i, step in enumerate(steps)] return "\n".join(steps) except Exception as e: logger.error(f"Error formatting steps: {str(e)}") return f"Error formatting your steps: {str(e)}" # Knowledge Base Search Interface demo1 = gr.Interface( fn=search_knowledge_base, inputs=[gr.Textbox(label="Technical Issue", placeholder="Enter your technical problem (e.g., wifi connection problem)")], outputs=[gr.Textbox(label="Solution")], title="Knowledge Base Search", description="Enter a technical issue to search for solutions in the knowledge base." ) # Web Search Interface demo2 = gr.Interface( fn=search_web, inputs=[gr.Textbox(label="Search Query", placeholder="Enter your search query (e.g., latest tech news)")], outputs=[gr.Textbox(label="Search Results")], title="Web Search", description="Enter a search query to get real web search results from DuckDuckGo." ) # Response Formatter Interface demo3 = gr.Interface( fn=format_response, inputs=[gr.Textbox(label="Raw Steps", placeholder="Enter steps separated by periods or semicolons")], outputs=[gr.Textbox(label="Formatted Steps")], title="Response Formatter", description="Enter raw steps separated by periods or semicolons to format them as a numbered list." ) # Combine all interfaces using Tabs demo = gr.TabbedInterface([demo1, demo2, demo3], ["Knowledge Base", "Web Search", "Formatter"]) if __name__ == "__main__": demo.launch()