import os import streamlit as st from openai import OpenAI # ===== CONFIG ===== OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") or st.secrets.get("OPENAI_API_KEY", None) st.set_page_config(page_title="Procelevate AI Agent", page_icon="πŸ€–", layout="wide") st.title("πŸ€– Procelevate Agent Suite") if not OPENAI_API_KEY: st.warning("⚠️ OPENAI_API_KEY not found. Set it in the Space secrets.") client = OpenAI(api_key=OPENAI_API_KEY) if OPENAI_API_KEY else None def call_llm(system_prompt: str, user_prompt: str) -> str: if client is None: return "❗OPENAI_API_KEY not set." resp = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], temperature=0.25, ) return resp.choices[0].message.content # ===== EXISTING FUNCTIONS ===== def generate_po(buyer_name, buyer_address, supplier_name, supplier_email, items_text, payment_terms, notes): system_prompt = """You are a Purchase Order (PO) generation assistant for Procelevate. Output in markdown with headings, line-item table, and totals. Assume 18% tax if missing.""" user_prompt = f""" Buyer: - Name: {buyer_name} - Address: {buyer_address} Supplier: - Name: {supplier_name} - Email: {supplier_email} Line Items: {items_text} Payment Terms: {payment_terms} Notes: {notes} """ return call_llm(system_prompt, user_prompt) def generate_email_reply(incoming_email, reply_goal, tone): system_prompt = """You are an AI email responder for Procelevate Consulting & Academy. Write a concise reply in the requested tone. End with 'Regards, Procelevate Team'.""" user_prompt = f""" Incoming email: \"\"\"{incoming_email}\"\"\" Goal: {reply_goal} Tone: {tone} """ return call_llm(system_prompt, user_prompt) # ===== NEW: QUOTATION β†’ PR β†’ PO PIPELINE ===== def extract_text_from_upload(uploaded_file): # simplest path: handle text files directly if uploaded_file is None: return "" if uploaded_file.type == "text/plain": return uploaded_file.read().decode("utf-8") # for PDFs we need a parser; if pdfplumber not installed, just say so if uploaded_file.type == "application/pdf": try: import pdfplumber text_parts = [] with pdfplumber.open(uploaded_file) as pdf: for page in pdf.pages: text_parts.append(page.extract_text() or "") return "\n".join(text_parts) except Exception as e: return f"PDF uploaded but could not parse: {e}" # fallback return uploaded_file.read().decode("utf-8", errors="ignore") def create_pr_from_quotation(quotation_text, buyer_org): system_prompt = """You are a purchasing assistant. Given a supplier quotation text, extract: - supplier_name - line_items (description, qty, unit_price if present) - currency (guess if missing) Return a clean JSON-like structure representing a Purchase Requisition (PR) for internal approval.""" user_prompt = f""" Organisation: {buyer_org} Quotation text: \"\"\"{quotation_text}\"\"\" Return PR as JSON with keys: pr_title, supplier_name, currency, line_items, total_if_available. """ return call_llm(system_prompt, user_prompt) def create_approval_email(pr_json_text, approver_email="approver@example.com"): system_prompt = """You are an approval workflow assistant. Write an approval request email for a PR. Email must include: PR title, supplier, amount, and a clear approve/reject instruction. Don't actually send it, just draft.""" user_prompt = f""" PR details (JSON): {pr_json_text} Approver email: {approver_email} Write the approval email. """ return call_llm(system_prompt, user_prompt) def create_po_from_pr(pr_json_text, buyer_name, buyer_address, supplier_email): system_prompt = """You are a PO generator. Convert the approved PR (JSON) into a Purchase Order in markdown. Include buyer, supplier, line items table, totals, and payment terms (assume Net 30).""" user_prompt = f""" Buyer name: {buyer_name} Buyer address: {buyer_address} Supplier email: {supplier_email} PR JSON: {pr_json_text} """ return call_llm(system_prompt, user_prompt) def create_supplier_email(po_markdown, supplier_email): system_prompt = """You are a business email writer. Write an email to supplier attaching/sending PO details. Keep it formal, short. Mention PO number if present.""" user_prompt = f""" Supplier: {supplier_email} PO content: {po_markdown} """ return call_llm(system_prompt, user_prompt) # ===== UI TABS ===== tab1, tab2, tab3 = st.tabs(["πŸ“„ PO Automation", "πŸ“§ Email Responder", "πŸ“¦ Quotation β†’ PR β†’ PO"]) # --- TAB 1: Existing PO form --- with tab1: st.subheader("πŸ“„ Generate Purchase Order") col1, col2 = st.columns(2) with col1: buyer_name = st.text_input("Buyer Name", value="Procelevate Consulting") buyer_address = st.text_area("Buyer Address", value="Bengaluru, Karnataka, India", height=80) payment_terms = st.text_input("Payment Terms", value="Net 30 days") with col2: supplier_name = st.text_input("Supplier Name", value="") supplier_email = st.text_input("Supplier Email", value="") notes = st.text_area("Additional Notes", value="Please deliver services as per agreed SOW.", height=80) items_text = st.text_area( "Line Items (one per line)", value="1. AI/ML Bootcamp Seats, Qty 10, Unit Price 2999\n2. Consulting Hours, Qty 5, Unit Price 1500", height=120 ) if st.button("Generate PO", key="gen_po_basic"): po_md = generate_po( buyer_name, buyer_address, supplier_name, supplier_email, items_text, payment_terms, notes ) st.markdown("---") st.markdown("### βœ… Generated PO") st.markdown(po_md) # --- TAB 2: Email responder --- with tab2: st.subheader("πŸ“§ Generate Email Reply") incoming_email = st.text_area( "Incoming email", value="Hi Mahesh, we are interested in your Smart Daycare Suite. Can you share pricing and a demo slot?", height=140 ) reply_goal = st.text_input( "What should the reply do?", value="Acknowledge, share that we have multiple AI/ML modules, and propose 30-min demo." ) tone = st.selectbox( "Tone", options=["Professional", "Friendly", "Formal-Client", "Follow-up/Reminder"], index=0 ) if st.button("Generate Reply", key="gen_reply"): reply_text = generate_email_reply(incoming_email, reply_goal, tone) st.markdown("---") st.markdown("### βœ… Reply Email") st.markdown(reply_text) # --- TAB 3: Quotation β†’ PR β†’ PO --- with tab3: st.subheader("πŸ“¦ Quotation β†’ PR β†’ PO") st.write("Upload supplier quotation, let the model draft PR, generate approval mail, and convert to PO after approval.") quotation_file = st.file_uploader("Upload quotation (PDF or .txt)", type=["pdf", "txt"]) buyer_org = st.text_input("Buyer Org / Company", value="Procelevate Consulting") supplier_email_q = st.text_input("Supplier Email (for final PO)", value="supplier@example.com") buyer_address_q = st.text_input("Buyer Address", value="Bengaluru, Karnataka, India") if st.button("1️⃣ Extract β†’ Create PR"): quotation_text = extract_text_from_upload(quotation_file) st.markdown("**Extracted text (preview):**") st.code(quotation_text[:800] or "No text extracted.", language="text") pr_json_text = create_pr_from_quotation(quotation_text, buyer_org) st.markdown("### βœ… Draft PR (JSON-like)") st.code(pr_json_text, language="json") st.session_state["latest_pr"] = pr_json_text st.success("PR drafted. Now generate approval email below.") if "latest_pr" in st.session_state: if st.button("2️⃣ Generate Approval Email"): approval_email = create_approval_email(st.session_state["latest_pr"]) st.markdown("### βœ… Approval Email (send this via Outlook/Gmail/n8n):") st.markdown(approval_email) st.session_state["approval_email"] = approval_email if "latest_pr" in st.session_state: if st.button("3️⃣ Simulate Approval β†’ Generate PO"): po_md = create_po_from_pr(st.session_state["latest_pr"], buyer_org, buyer_address_q, supplier_email_q) st.markdown("### βœ… Generated PO (from approved PR)") st.markdown(po_md) st.session_state["po_md"] = po_md if "po_md" in st.session_state: if st.button("4️⃣ Prepare Supplier Email"): supplier_mail = create_supplier_email(st.session_state["po_md"], supplier_email_q) st.markdown("### βœ… Supplier Email (copy & send)") st.markdown(supplier_mail) st.info("To auto-send this, connect SMTP or n8n webhook.")