diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """ -Apex Biotical Veterinary WhatsApp Bot - Premium Edition -The most effective and accurate veterinary chatbot in the market +Apex Biotical Veterinary WhatsApp Assistant - Premium Edition +The most effective and accurate veterinary Assistant in the market """ import os @@ -60,7 +60,11 @@ logger = logging.getLogger(__name__) load_dotenv() # Initialize FastAPI app -app = FastAPI(title="Apex Biotical Veterinary Bot", version="2.0.0") +app = FastAPI(title="Apex Biotical Veterinary Assistant", version="2.0.0") + +# Ensure static and uploads directories exist before mounting +os.makedirs('static', exist_ok=True) +os.makedirs('uploads', exist_ok=True) # Mount static files and templates app.mount("/static", StaticFiles(directory="static"), name="static") @@ -256,7 +260,7 @@ async def download_voice_file(media_url: str, filename: str) -> str: return None async def transcribe_voice_with_openai(file_path: str) -> str: - """Transcribe voice file using OpenAI Whisper with improved error handling and language restriction""" + """Transcribe voice file using OpenAI Whisper with comprehensive veterinary domain system prompt""" try: # Check if file exists and has content if not os.path.exists(file_path): @@ -270,13 +274,82 @@ async def transcribe_voice_with_openai(file_path: str) -> str: logger.info(f"[Transcribe] Transcribing file: {file_path} (size: {file_size} bytes)") - # First attempt with English-specific prompt and language restriction + # Comprehensive system prompt for veterinary WhatsApp assistant + system_prompt = """ +You are transcribing voice messages for Apex Biotical Veterinary WhatsApp Assistant. This is a professional veterinary products chatbot. + +CONTEXT: Users can speak product names, menu selections, numbers, and general queries in English or Urdu. + +PRODUCT NAMES (Veterinary Products): +- Hydropex (electrolyte supplement) +- Respira Aid Plus (respiratory support) +- Heposel (liver tonic) +- Bromacid (respiratory/mucolytic) +- Hexatox (liver & kidney support) +- APMA Fort (mycotoxin binder) +- Para C.E (heat stress support) +- Tribiotic (antibiotic) +- PHYTO-SAL (phytogenic supplement) +- Mycopex Super (mycotoxin binder) +- Eflin KT-20 (antibiotic) +- Salcozine ST-30 (anticoccidial) +- Oftilex UA-10 (antibiotic) +- Biscomin 10 (injectable antibiotic) +- Apvita Plus (vitamin supplement) +- B-G Aspro-C (aspirin + vitamin C) +- EC-Immune (immune booster) +- Liverpex (liver tonic) +- Symodex (multivitamin) +- Respira Aid (respiratory support) +- Adek Gold (multivitamin) +- Immuno DX (immune enhancer) + +MENU SELECTIONS: +- Main menu options: 1, 2, 3, 4 +- Product numbers: 1-23 +- Category numbers: 1-10 +- Navigation: main, menu, back, home, start + +NUMBERS (English & Urdu): +English: one, two, three, four, five, six, seven, eight, nine, ten, eleven, twelve, thirteen, fourteen, fifteen, sixteen, seventeen, eighteen, nineteen, twenty, twenty-one, twenty-two, twenty-three +Urdu (Roman): aik, ek, do, teen, char, panch, che, sat, ath, nau, das, gyara, bara, tera, choda, pandra, sola, satara, athara, unnees, bees, ikkees, baees, tees +Urdu (Script): ایک, دو, تین, چار, پانچ, چھ, سات, آٹھ, نو, دس, گیارہ, بارہ, تیرہ, چودہ, پندرہ, سولہ, سترہ, اٹھارہ, انیس, بیس, اکیس, بائیس, تئیس + +COMMON GREETINGS: +English: hi, hello, hey, good morning, good afternoon, good evening, how are you +Urdu: salam, assalamu alaikum, adaab, namaste, khuda hafiz + +MENU COMMANDS: +English: search, browse, download, catalog, contact, availability, main menu, option, number, choice +Urdu: تلاش, براؤز, ڈاؤن لوڈ, کیٹلاگ, رابطہ, دستیابی, مین مینو, آپشن, نمبر, اختیار + +TRANSCRIPTION RULES: +1. Transcribe product names exactly as listed above +2. Convert spoken numbers to digits (1, 2, 3, etc.) +3. Handle both English and Urdu speech +4. Preserve exact spelling for product names +5. Convert menu selections to numbers +6. Handle common transcription errors (opium->option, numara->number) +7. Maintain context for veterinary domain + +EXAMPLES: +- "hydropex" -> "hydropex" +- "respira aid plus" -> "respira aid plus" +- "option number one" -> "1" +- "aik" -> "1" +- "do" -> "2" +- "main menu" -> "main" +- "salam" -> "salam" +- "search products" -> "search products" +""" + + # First attempt with comprehensive system prompt with open(file_path, 'rb') as audio_file: transcript = openai.Audio.transcribe( model="whisper-1", file=audio_file, - language="en", # Force English first - prompt="This is a voice message for a veterinary products bot. Language: English or Urdu only. Common greetings: hi, hello, hey, salam, assalamualaikum. Numbers: one, two, three, 1, 2, 3, aik, do, teen. Menu options: search, browse, download, catalog, products, categories, contact, availability. Products: hydropex, heposel, bromacid, tribiotic, symodex, adek gold. Please transcribe clearly and accurately." + language="en", # Start with English + prompt=system_prompt ) transcribed_text = transcript.text.strip() @@ -286,12 +359,51 @@ async def transcribe_voice_with_openai(file_path: str) -> str: if not transcribed_text or len(transcribed_text.strip()) < 2: logger.warning(f"[Transcribe] First attempt failed, trying with Urdu-specific prompt") + urdu_system_prompt = """ +You are transcribing Urdu voice messages for Apex Biotical Veterinary WhatsApp Assistant. + +PRODUCT NAMES (Urdu/English): +- ہائیڈروپیکس (Hydropex) +- ریسپیرا ایڈ پلس (Respira Aid Plus) +- ہیپوسیل (Heposel) +- بروماسڈ (Bromacid) +- ہیکساٹوکس (Hexatox) +- اے پی ایم اے فورٹ (APMA Fort) +- پیرا سی ای (Para C.E) +- ٹرائی بیوٹک (Tribiotic) +- فائٹو سال (PHYTO-SAL) +- مائیکوپیکس سپر (Mycopex Super) + +URDU NUMBERS: +- ایک (1), دو (2), تین (3), چار (4), پانچ (5) +- چھ (6), سات (7), آٹھ (8), نو (9), دس (10) +- گیارہ (11), بارہ (12), تیرہ (13), چودہ (14), پندرہ (15) +- سولہ (16), سترہ (17), اٹھارہ (18), انیس (19), بیس (20) +- اکیس (21), بائیس (22), تئیس (23) + +URDU GREETINGS: +- سلام (salam), السلام علیکم (assalamu alaikum) +- آداب (adaab), نمستے (namaste), خدا حافظ (khuda hafiz) + +URDU MENU COMMANDS: +- مین مینو (main menu), آپشن (option), نمبر (number) +- تلاش (search), براؤز (browse), ڈاؤن لوڈ (download) +- کیٹلاگ (catalog), رابطہ (contact), دستیابی (availability) + +TRANSCRIPTION RULES: +1. Transcribe Urdu words in Urdu script +2. Convert Urdu numbers to digits +3. Handle mixed Urdu-English speech +4. Preserve product names exactly +5. Convert menu selections to numbers +""" + with open(file_path, 'rb') as audio_file: transcript = openai.Audio.transcribe( model="whisper-1", file=audio_file, language="ur", # Force Urdu - prompt="This is a voice message in Urdu for a veterinary products bot. Common Urdu greetings: سلام, ہیلو, ہائے, السلام علیکم, وعلیکم السلام. Numbers: ایک, دو, تین, چار, پانچ, 1, 2, 3, 4, 5. Menu options: تلاش, براؤز, ڈاؤن لوڈ, کیٹلاگ, پروڈکٹ, کیٹیگری, رابطہ, دستیابی. Products: ہائیڈروپیکس, ہیپوسیل, بروماسڈ, ٹرائیبیوٹک. Please transcribe clearly in Urdu or English." + prompt=urdu_system_prompt ) transcribed_text = transcript.text.strip() @@ -301,11 +413,35 @@ async def transcribe_voice_with_openai(file_path: str) -> str: if not transcribed_text or len(transcribed_text.strip()) < 2: logger.warning(f"[Transcribe] Second attempt failed, trying with mixed language prompt") + mixed_system_prompt = """ +You are transcribing voice messages for a veterinary products WhatsApp assistant. The user may speak in English, Urdu, or a mix of both languages. + +PRODUCT NAMES (exact spelling required): +Hydropex, Respira Aid Plus, Heposel, Bromacid, Hexatox, APMA Fort, Para C.E, Tribiotic, PHYTO-SAL, Mycopex Super, Eflin KT-20, Salcozine ST-30, Oftilex UA-10, Biscomin 10, Apvita Plus, B-G Aspro-C, EC-Immune, Liverpex, Symodex, Respira Aid, Adek Gold, Immuno DX + +NUMBERS (convert to digits): +English: one->1, two->2, three->3, etc. +Urdu: aik->1, ek->1, do->2, teen->3, etc. + +MENU COMMANDS: +main, menu, back, home, start, option, number, search, browse, download, catalog, contact, availability + +GREETINGS: +hi, hello, salam, assalamu alaikum, adaab, namaste + +TRANSCRIPTION RULES: +1. Transcribe exactly what you hear +2. Convert numbers to digits +3. Preserve product names exactly +4. Handle both languages +5. Convert menu selections to numbers +""" + with open(file_path, 'rb') as audio_file: transcript = openai.Audio.transcribe( model="whisper-1", file=audio_file, - prompt="This is a voice message for a veterinary products bot. Language: English or Urdu only. Common words: hi, hello, salam, one, two, three, aik, do, teen, search, browse, download, catalog, products, categories, contact, availability, hydropex, heposel, bromacid, tribiotic, symodex, adek gold. Please transcribe any speech you can hear, even if unclear. Numbers and menu selections are important." + prompt=mixed_system_prompt ) transcribed_text = transcript.text.strip() @@ -324,7 +460,7 @@ async def transcribe_voice_with_openai(file_path: str) -> str: return None def process_voice_input(text: str) -> str: - """Process and clean voice input text with common transcription error correction""" + """Process and clean voice input text with veterinary domain-specific transcription error correction""" if not text: return "" @@ -337,12 +473,9 @@ def process_voice_input(text: str) -> str: # Basic punctuation cleanup processed_text = processed_text.replace(' ,', ',').replace(' .', '.') - # Common transcription error corrections + # Veterinary domain-specific transcription error corrections transcription_fixes = { - 'bye': 'hi', - 'goodbye': 'hello', - 'good bye': 'hello', - 'good by': 'hello', + # Common menu selection errors 'opium': 'option', 'opium numara': 'option number', 'opium number': 'option number', @@ -361,6 +494,7 @@ def process_voice_input(text: str) -> str: 'numbra 1': 'number 1', 'numbra 2': 'number 2', 'numbra 3': 'number 3', + # Number fixes - only when they appear as standalone numbers 'aik': '1', 'ek': '1', @@ -378,6 +512,7 @@ def process_voice_input(text: str) -> str: 'ath': '8', 'nau': '9', 'das': '10', + # Navigation command fixes 'man': 'main', 'men': 'main', @@ -387,7 +522,34 @@ def process_voice_input(text: str) -> str: 'menu': 'main', 'home': 'main', 'back': 'main', - 'return': 'main' + 'return': 'main', + + # Veterinary product name corrections + 'hydro pex': 'hydropex', + 'hydro pex': 'hydropex', + 'respira aid': 'respira aid plus', + 'respira aid plus': 'respira aid plus', + 'hepo sel': 'heposel', + 'brom acid': 'bromacid', + 'hexa tox': 'hexatox', + 'apma fort': 'apma fort', + 'para c': 'para c.e', + 'para ce': 'para c.e', + 'tribiotic': 'tribiotic', + 'phyto sal': 'phyto-sal', + 'mycopex': 'mycopex super', + 'mycopex super': 'mycopex super', + 'eflin': 'eflin kt-20', + 'salcozine': 'salcozine st-30', + 'oftilex': 'oftilex ua-10', + 'biscomin': 'biscomin 10', + 'apvita': 'apvita plus', + 'bg aspro': 'b-g aspro-c', + 'ec immune': 'ec-immune', + 'liverpex': 'liverpex', + 'symodex': 'symodex', + 'adek': 'adek gold', + 'immuno': 'immuno dx' } # Apply transcription fixes - but be careful with Islamic greetings @@ -646,18 +808,22 @@ context_manager = VeterinaryContextManager() # Enhanced product response with veterinary domain expertise def generate_veterinary_product_response(product_info: Dict[str, Any], user_context: Dict[str, Any]) -> str: """Generate comprehensive veterinary product response with intelligent information handling""" + def clean_text(text): if pd.isna(text) or text is None: return "Not specified" return str(text).strip() + # Extract product details product_name = clean_text(product_info.get('Product Name', '')) product_type = clean_text(product_info.get('Type', '')) category = clean_text(product_info.get('Category', '')) indications = clean_text(product_info.get('Indications', '')) + # Check for PDF link in the CSV data pdf_link = "" try: + # Load CSV data to check for PDF link csv_data = pd.read_csv('Veterinary.csv') product_row = csv_data[csv_data['Product Name'] == product_name] if not product_row.empty: @@ -666,15 +832,27 @@ def generate_veterinary_product_response(product_info: Dict[str, Any], user_cont pdf_link = brochure_link.strip() except Exception as e: logger.warning(f"Error checking PDF link for {product_name}: {e}") - response = f"""🧪 *Name:* {product_name}\n📦 *Type:* {product_type}\n🏥 *Category:* {category}\n💊 *Used For:* {indications}""" + + # Build the response + response = f"""🧪 *Name:* {product_name} +📦 *Type:* {product_type} +🏥 *Category:* {category} +💊 *Used For:* {indications}""" + + # Add PDF link if available, in the requested format if pdf_link: response += f"\n\n📄 Product Brochure Available\n🔗 {product_name} PDF:\n{pdf_link}" + + # Add menu options response += f""" -\n💬 *Available Actions:* + +💬 *Available Actions:* 1️⃣ Talk to Veterinary Consultant 2️⃣ Inquire About Availability 3️⃣ Back to Main Menu -\n💬 Select an option or ask about related products""" + +💬 Select an option or ask about related products""" + return response def clean_text_for_pdf(text: str) -> str: @@ -808,10 +986,8 @@ def generate_veterinary_pdf(product: Dict[str, Any]) -> bytes: async def send_catalog_pdf(phone_number: str): """Send the complete product catalog as a link to the PDF""" try: - # Use the static file URL for Hugging Face Spaces - server_url = os.getenv("SERVER_URL", "https://your-huggingface-space-url.hf.space") - catalog_url = f"{server_url}/static/Hydropex.pdf" - + # Use the correct Google Drive link converted to direct download format + catalog_url = "https://drive.google.com/uc?export=download&id=1mxpkFf3DY-n3QHzZBe_CdksR-gHu2f_0" message = ( "📋 *Apex Biotical Veterinary Products Catalog*\n\n" "📄 Here's your complete product catalog with all our veterinary products:\n" @@ -838,16 +1014,16 @@ async def send_individual_product_pdf(phone_number: str, product: Dict[str, Any] filename = f"{safe_name}_{timestamp}.pdf" # Save PDF to uploads directory - uploads_dir = "uploads" + uploads_dir = "../uploads" os.makedirs(uploads_dir, exist_ok=True) pdf_path = os.path.join(uploads_dir, filename) with open(pdf_path, 'wb') as f: f.write(pdf_content) - # Generate download URL for Hugging Face Spaces - server_url = os.getenv("SERVER_URL", "https://your-huggingface-space-url.hf.space") - download_url = f"{server_url}/uploads/{filename}" + # Generate download URL + base_url = os.getenv("PUBLIC_BASE_URL", "http://localhost:8000") + download_url = f"{base_url}/uploads/{filename}" # Send PDF via WhatsApp media success = send_whatsjet_message( @@ -862,7 +1038,7 @@ async def send_individual_product_pdf(phone_number: str, product: Dict[str, Any] if success: message = ( f"📄 *{product_name} - Product Information*\n\n" - f"📎 [Direct Download Link]({download_url})\n\n" + "📎 [Direct Download Link]({download_url})\n\n" "💬 *If the PDF didn't download, use the link above*\n" "Type 'main' to return to main menu." ) @@ -871,7 +1047,7 @@ async def send_individual_product_pdf(phone_number: str, product: Dict[str, Any] # If media send failed, send only the link message = ( f"📄 *{product_name} - Product Information*\n\n" - f"📎 [Download Product PDF]({download_url})\n\n" + "📎 [Download Product PDF]({download_url})\n\n" "💬 *Click the link above to download the product information*\n" "Type 'main' to return to main menu." ) @@ -1006,7 +1182,6 @@ def send_whatsjet_message(phone_number: str, message: str, media_type: str = Non except Exception as e: logger.error(f"[WhatsJet] Exception preparing text chunk: {str(e)}") return False - logger.info(f"[WhatsJet] Successfully sent complete text message to {phone_number}") return True @@ -1039,15 +1214,6 @@ def send_whatsjet_media_image_only(phone_number: str, image_url: str, filename: logger.error(f"[WhatsJet] Exception sending image only: {e}") return False -# Test endpoint for WhatsJet media format debugging -@app.get("/test-whatsjet-media-formats") -async def test_whatsjet_media_formats(): - try: - resp = requests.get("https://api.whatsjet.com", timeout=5) - return {"status": resp.status_code, "text": resp.text[:200]} - except Exception as e: - return {"error": str(e)} - # --- Health Check Endpoint --- @app.get("/health") async def health_check(): @@ -1094,6 +1260,9 @@ async def get_catalog(): @app.get("/", response_class=HTMLResponse) async def root(): return """ +

Apex Biotical Veterinary WhatsApp Assistant

+

The Assistant is running! Use the API endpoints for WhatsApp integration.

+