""" Hugging Face Gradio Interface for RFP Analyzer """ import gradio as gr import json import os from rfp_analyzer import analyze_rfp, load_rubric, AnalyzerConfig # Load rubric once at startup rubric = load_rubric("rubric.yaml") def analyze_rfp_gradio(pdf_file, target_states, partner_known=False): """ Gradio interface function for RFP analysis """ if pdf_file is None: return "Please upload a PDF file", "", "" try: # Read PDF bytes with open(pdf_file.name, 'rb') as f: pdf_bytes = f.read() # Prepare metadata meta = { "target_states": target_states.split(",") if target_states else [], "partner_known": partner_known } # Configure analyzer for HuggingFace Spaces deployment # Try multiple environment variable names for HF token hf_token = ( os.environ.get("HF_TOKEN") or os.environ.get("HF_API_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN") or "" ) config = AnalyzerConfig( use_hf_api=True, hf_model="meta-llama/llama-2-7b-hf", # Using your linked model enable_ai_summaries=True, hf_token=hf_token, temperature=0.1 ) # Debug: Show token status if hf_token: print(f"✅ HF_TOKEN configured: {hf_token[:10]}...{hf_token[-4:]}") else: print("⚠️ HF_TOKEN not found - AI features will be disabled") print(" Set HF_TOKEN in Space secrets: https://huggingface.co/spaces/Varun10000/qwertyuiop/settings") # Analyze RFP result = analyze_rfp(pdf_bytes, rubric, config, meta) # Format results for display status = f"## Decision: {result['status']}\n\n" status += f"**Score:** {result.get('score', 0):.2%}\n\n" # AI Insights ai_insights = "## 📋 AI-Extracted RFP Requirements\n\n" if result.get('ai_insights'): insights = result['ai_insights'] # Scope if insights.get('scope'): scope = insights['scope'] ai_insights += f"### 🔵 Scope Summary & Deliverables\n\n" ai_insights += f"{scope.get('scope_summary_and_work', 'N/A')}\n\n" ai_insights += f"**Type of Work:** {scope.get('type_of_work', 'N/A')}\n\n" ai_insights += f"📍 {scope.get('reference', '')}\n\n" ai_insights += "---\n\n" # Certifications if insights.get('certifications'): certs = insights['certifications'] ai_insights += f"### 🟢 Certifications Required\n\n" if certs.get('detailed_text'): ai_insights += f"{certs['detailed_text']}\n\n" ai_insights += "**Business Certifications:**\n" ai_insights += f"- SBE: {'✅' if certs.get('sbe_required') else '⬜'}\n" ai_insights += f"- MWBE: {'✅' if certs.get('mwbe_required') else '⬜'}\n" ai_insights += f"- MBE: {'✅' if certs.get('mbe_required') else '⬜'}\n" ai_insights += f"- WBE: {'✅' if certs.get('wbe_required') else '⬜'}\n\n" ai_insights += f"📍 {certs.get('reference', '')}\n\n" ai_insights += "---\n\n" # Eligibility if insights.get('eligibility_requirements'): elig = insights['eligibility_requirements'] ai_insights += f"### 🟡 Eligibility & Requirements\n\n" ai_insights += f"{elig.get('requirements_summary', 'N/A')}\n\n" if elig.get('years_experience'): ai_insights += f"**Years of Experience Required:** {elig['years_experience']}+ years\n\n" if elig.get('past_experience_required'): ai_insights += f"**Past Experience:**\n{elig['past_experience_required']}\n\n" ai_insights += f"📍 {elig.get('reference', '')}\n\n" # Detailed Analysis details = "## Detailed Analysis\n\n" details += f"**Analysis Time:** {result.get('analysis_time', 'N/A')}\n\n" details += f"**Method:** {result.get('method', 'N/A')}\n\n" if result.get('reasons'): details += "### Reasons:\n" for reason in result['reasons']: details += f"- {reason}\n" details += "\n" # Strategic Notes if result.get('strategic_notes'): details += "### Strategic Notes:\n\n" for note in result['strategic_notes']: details += f"{note}\n\n" # Full JSON for advanced users full_json = json.dumps(result, indent=2) return status, ai_insights, details, full_json except Exception as e: error_msg = f"## Error\n\nFailed to analyze RFP: {str(e)}" return error_msg, "", "", str(e) # Create Gradio interface with gr.Blocks(title="RFP Go/No-Go Analyzer", theme=gr.themes.Soft()) as demo: gr.Markdown(""" # 📋 RFP Go/No-Go Decision Analyzer Upload an RFP PDF to get instant AI-powered analysis with: - ✅ Go/No-Go recommendation - 📊 Comprehensive scope, certification, and eligibility extraction - 🎯 Strategic insights and compliance checks - ⚡ Fast pattern-based extraction (<1 second) **Powered by:** Llama3 AI + Pattern Matching """) with gr.Row(): with gr.Column(scale=1): pdf_input = gr.File( label="Upload RFP PDF", file_types=[".pdf"], type="filepath" ) target_states = gr.Textbox( label="Target States (comma-separated)", placeholder="Virginia, Maryland, DC", value="" ) partner_known = gr.Checkbox( label="Partner Already Known?", value=False ) analyze_btn = gr.Button("🚀 Analyze RFP", variant="primary", size="lg") with gr.Column(scale=2): status_output = gr.Markdown(label="Decision") with gr.Row(): with gr.Column(): ai_insights_output = gr.Markdown(label="AI Insights") with gr.Column(): details_output = gr.Markdown(label="Detailed Analysis") with gr.Accordion("📄 Full JSON Response", open=False): json_output = gr.Code(label="Complete Analysis Data", language="json") # Connect button to function analyze_btn.click( fn=analyze_rfp_gradio, inputs=[pdf_input, target_states, partner_known], outputs=[status_output, ai_insights_output, details_output, json_output] ) gr.Markdown(""" --- ### 📚 Features - **Ultra-Fast Analysis:** Pattern-based extraction in <1 second - **Page Citations:** Exact page numbers for all extracted data - **Comprehensive Extraction:** Scope, Certifications, Eligibility, Past Experience - **Go/No-Go Decision:** AI-powered recommendation with criteria scoring - **Strategic Notes:** Actionable insights for proposal strategy ### 🔧 Technical Details - **Text Extraction:** 99% accuracy with PyMuPDF - **Pattern Matching:** Advanced regex for instant field detection - **AI Model:** Llama3 (optional for enhanced summaries) - **Processing Time:** 0.1-0.5 seconds per RFP """) # Launch app if __name__ == "__main__": demo.launch( server_name="0.0.0.0", server_port=7860, share=False )