HJSR / app.py
Varun10000's picture
Upload 4 files
98cdd03 verified
Raw
History Blame Contribute Delete
8.07 kB
"""
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
)