Spaces:
Runtime error
Runtime error
File size: 9,085 Bytes
559ff90 7c6188a 559ff90 7c6188a 5d377bc 559ff90 5d377bc 559ff90 5d377bc 559ff90 5d377bc 559ff90 5d377bc 559ff90 5d377bc 559ff90 5d377bc 7c6188a 559ff90 5d377bc 559ff90 5d377bc 559ff90 5d377bc 7c6188a 5d377bc 7c6188a 559ff90 5d377bc 559ff90 5d377bc 559ff90 5d377bc 559ff90 5d377bc 559ff90 7c6188a 5d377bc 559ff90 5d377bc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
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.")
|