diff --git a/routes/ai_summary.py b/routes/ai_summary.py index 71cee5e..6597365 100644 --- a/routes/ai_summary.py +++ b/routes/ai_summary.py @@ -196,122 +196,44 @@ _SYSTEM_PROMPT = ( "Write \"Not specified\" for any field not found in the documents — never guess." ) -# Stage 1 — extraction prompt (always sent). Kept compact to minimise payload size. +# Stage 1 — extraction prompt (always sent). _EXTRACTION_PROMPT = """\ -Analyze the {n} solicitation document(s) below as one combined package. -Fill in every table and section. Write **"Not specified"** for missing fields. +The user has provided {n} document(s). Treat all provided content as a single combined source \ +— do not analyze each file individually. Extract the following information once, \ +consolidating details from all documents. -Our office: **{office}** — use as origin for travel estimates. +IMPORTANT — Our office is located at: + {office} +Use this as the ORIGIN address for all driving distance and travel time calculations in field #9 below. ---- +Extract and clearly label the following fields (write "N/A" if not found): -## Solicitation Overview + 1. Solicitation Number + 2. Solicitation Type (e.g. RFP, RFQ, IFB, etc.) + 3. Set-Aside (e.g. Small Business, 8(a), N/A) + 4. Description / Scope of Work + 5. Work Site / Location(s) + 6. Pre-Proposal Conference / Site-Visit (date, time, full address) + 7. Point of Contact (POC) (name, phone, email) + 8. Total Square Footage (if applicable) + 9. Driving Distance & Travel Time + - Origin: {office} + - Destination: Pre-Proposal Conference or primary Work Site address + - Provide your best estimate of driving distance (miles) and typical driving time using major highways + - Note that these are AI estimates; actual times may vary with traffic + 10. Last Day to Submit Questions + 11. Due Date & Time + 12. Any other notable requirements or deadlines -| Field | Value | -|---|---| -| Solicitation Number | | -| Solicitation Type | (RFP / RFQ / IFB / IDIQ / BPA / etc.) | -| Issuing Agency / Office | | -| Set-Aside | (Small Business / 8(a) / SDVOSB / HUBZone / WOSB / Unrestricted / etc.) | -| Contract Type | (FFP / T&M / Cost-Plus / IDIQ / etc.) | -| Contract Period | | -| NAICS Code | | -| Estimated Value | | +Then provide a detailed OVERALL SUMMARY covering: ---- + A. Scope of Work + B. Contract Period + C. Proposal Submission Requirements + D. Key Deadlines & Action Items -## Scope of Work - -*(Detail required services, deliverables, and performance standards. Use bullet points.)* - ---- - -## Performance Location(s) - -*(All work sites; whether remote or on-site work is permitted.)* - ---- - -## Key Dates & Deadlines - -| Milestone | Date & Time | -|---|---| -| Pre-Proposal Conference / Site Visit | | -| Questions Due | | -| **Proposal Due** | | -| Award Date | | -| Period of Performance Start | | -| Other Deadlines | | - ---- - -## Pre-Proposal Conference / Site Visit - -| | | -|---|---| -| Date & Time | | -| Full Address | | -| Attendance | (Mandatory / Optional / N/A) | -| RSVP Required | | - ---- - -## Point of Contact - -| | | -|---|---| -| Name / Title | | -| Phone | | -| Email | | -| Questions Submission Method | | - ---- - -## Proposal Requirements - -*(Format, page limits, volumes, submission method, number of copies.)* - ---- - -## Evaluation Factors - -*(Government's evaluation criteria and weights as stated in the solicitation.)* - ---- - -## Travel & Logistics - -| | | -|---|---| -| Origin | {office} | -| Destination | | -| Estimated Driving Distance | | -| Estimated Drive Time | | - -*(AI estimates — verify with a mapping service before scheduling.)* - ---- - -## Red Flags & Notable Requirements - -*(Security clearances, bonding, certifications, teaming restrictions, tight timelines, incumbent indicators, or other bid/no-bid risk factors.)* - ---- - -## Total Square Footage - -*(If applicable; write "N/A" if not.)* - ---- - -## Overall Summary - -- **What Is Being Procured:** -- **Contract Period & Value:** -- **Key Constraints:** -- **Immediate Action Items & Deadlines:** - ---- +Be precise, detailed, and use bullet points throughout. +If information is not explicitly stated in the documents, note it as "Not specified in the document." DOCUMENTS: {documents}""" @@ -321,30 +243,33 @@ DOCUMENTS: # on Groq's free tier. _CRITERIA_SUFFIX = """ ---- +================================================================================ +OPPORTUNITY ALIGNMENT EVALUATION +================================================================================ -## Opportunity Alignment Evaluation +After completing the extraction and summary above, evaluate whether this +opportunity aligns with our company's interests based on the following criteria. -Now evaluate this opportunity against our company's criteria below. - -**Our criteria:** +OUR EVALUATION CRITERIA: {criteria_list} -For each criterion provide: -- ✅ MEETS / ⚠️ PARTIALLY MEETS / ❌ DOES NOT MEET / ❓ CANNOT DETERMINE -- 1–2 sentences with specific evidence from the documents above. +For EACH criterion above: + - State whether the opportunity MEETS, DOES NOT MEET, or PARTIALLY MEETS it. + - Provide a brief, specific explanation citing details from the document(s). -**Overall Recommendation** — write exactly one of these lines (machine-read, do not alter): +Then provide an OVERALL RECOMMENDATION using EXACTLY one of these three labels +on its own line (this label is machine-read — do not alter it): RECOMMENDATION: PURSUE RECOMMENDATION: PASS RECOMMENDATION: UNCLEAR -PURSUE = clearly aligns with most criteria and is competitive. -PASS = fails one or more critical criteria or presents unacceptable risk. -UNCLEAR = insufficient information for a confident decision. +Use PURSUE if the opportunity clearly meets most criteria and presents strong +alignment. Use PASS if it clearly fails key criteria. Use UNCLEAR if the +documents lack sufficient information to make a confident determination. -**Executive Summary:** 3–4 sentences in plain business language explaining the recommendation.""" +End with a 2-3 sentence EXECUTIVE SUMMARY explaining your recommendation +in plain business language.""" def _call_groq(api_key: str, model: str, text: str, criteria: list) -> dict: