Download AgenticControl/draft_reply.py from Asad999/Texbase: direct link, hf CLI and curl.
- Browser
- Download file 5.8 kB
-
https://huggingface.co/spaces/Asad999/Texbase/resolve/main/AgenticControl/draft_reply.py
- Command line
-
hf download hf://spaces/Asad999/Texbase/AgenticControl/draft_reply.py
-
curl -L -o draft_reply.py https://huggingface.co/spaces/Asad999/Texbase/resolve/main/AgenticControl/draft_reply.py
5.8 kB
| import sys | |
| import json | |
| import sqlite3 | |
| import os | |
| import random | |
| import string | |
| from datetime import datetime | |
| from dotenv import load_dotenv | |
| from azure.ai.inference import ChatCompletionsClient | |
| from azure.core.credentials import AzureKeyCredential | |
| ROOT_DIR = os.environ.get('WORKSPACE_ROOT', '.') | |
| load_dotenv(dotenv_path=os.path.join(ROOT_DIR, 'backend/.env')) | |
| INBOX_DB = os.path.join(ROOT_DIR, 'Database/Inbox/inbox.db') | |
| REVIEW_DB = os.path.join(ROOT_DIR, 'Database/EmailsUnderReview/emailsUnderReview.db') | |
| SENDER = { | |
| "company": "Arooj Enterprises", | |
| "name": "Asad Irfan", | |
| "title": "Senior Marketing Manager", | |
| "website": "www.texbase.com", | |
| "certs": "ISO 14001, SEDEX, and OEKO-TEX", | |
| "capacity": "150,000 units/month" | |
| } | |
| def init_review_db(): | |
| conn = sqlite3.connect(REVIEW_DB) | |
| cursor = conn.cursor() | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS tracking ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| company_name TEXT, | |
| website TEXT, | |
| address TEXT, | |
| total_shipments TEXT, | |
| top_suppliers TEXT, | |
| hs_codes TEXT, | |
| company_description TEXT, | |
| key_executives TEXT, | |
| generated_subject TEXT, | |
| status TEXT DEFAULT 'pending', | |
| body_json TEXT, | |
| company_email TEXT, | |
| deep_research_pdf TEXT | |
| ) | |
| ''') | |
| conn.commit() | |
| return conn | |
| def draft_reply(inbox_id): | |
| if not GITHUB_TOKEN: | |
| print(json.dumps({"error": "GITHUB_TOKEN not found."})) | |
| return | |
| # 1. Fetch thread history | |
| conn_inbox = sqlite3.connect(INBOX_DB) | |
| c_inbox = conn_inbox.cursor() | |
| c_inbox.execute("SELECT thread_id, company_email, company_name, subject, last_messages_json FROM inbox_threads WHERE id = ?", (inbox_id,)) | |
| row = c_inbox.fetchone() | |
| if not row: | |
| print(json.dumps({"error": f"Inbox thread {inbox_id} not found."})) | |
| return | |
| thread_id, company_email, company_name, subject, last_messages_json = row | |
| history = json.loads(last_messages_json) | |
| history_text = "\n\n".join([f"From: {msg['from']}\nDate: {msg['date']}\nMessage:\n{msg['snippet']}" for msg in history]) | |
| # 2. Call LLM | |
| client = ChatCompletionsClient( | |
| endpoint="https://models.github.ai/inference", | |
| credential=AzureKeyCredential(GITHUB_TOKEN), | |
| ) | |
| prompt = f"""You are an expert B2B sales email writer for {SENDER['company']}. | |
| You are replying to an email thread with {company_name} ({company_email}). | |
| βββ EMAIL THREAD HISTORY βββ | |
| {history_text} | |
| βββ INSTRUCTIONS βββ | |
| - Write a professional, concise, and persuasive reply to the most recent message in the thread. | |
| - Address their questions or concerns directly. | |
| - Maintain our company persona: we are a garment manufacturer from Pakistan with a capacity of {SENDER['capacity']} and certifications {SENDER['certs']}. | |
| - Keep it under 150 words. | |
| - Structure it cleanly with paragraphs separated by \\n\\n. | |
| CRITICAL OUTPUT REQUIREMENT: | |
| - Output strictly valid JSON with exactly two keys: "subject" and "body". | |
| - "subject": Keep the thread subject but ensure it starts with 'Re: ' if not already. Current subject: {subject} | |
| - "body": Full email including greeting and sign-off as: {SENDER['name']} | {SENDER['title']} | {SENDER['company']} | {SENDER['website']} | |
| - THE BODY MUST INCLUDE \\n\\n (escaped newlines) BETWEEN EVERY PARAGRAPH. Do NOT output a single flat block of text! | |
| """ | |
| try: | |
| response = client.complete( | |
| messages=[ | |
| {"role": "system", "content": "You are a professional B2B cold email response writer. Output strictly in JSON format without markdown code blocks."}, | |
| {"role": "user", "content": prompt} | |
| ], | |
| model="gpt-4o", | |
| temperature=0.7, | |
| max_tokens=1000 | |
| ) | |
| reply_json_str = response.choices[0].message.content.strip() | |
| if reply_json_str.startswith("```json"): | |
| reply_json_str = reply_json_str[7:] | |
| if reply_json_str.endswith("```"): | |
| reply_json_str = reply_json_str[:-3] | |
| reply_data = json.loads(reply_json_str) | |
| new_subject = reply_data.get("subject", f"Re: {subject}") | |
| new_body = reply_data.get("body", "") | |
| # 3. Store in Review DB | |
| conn_review = init_review_db() | |
| c_review = conn_review.cursor() | |
| # Build payload similar to EmailGenerator | |
| body_json_payload = { | |
| "body": { | |
| "generated_content": new_body, | |
| "subject": new_subject, | |
| "outreach_data": { | |
| "company_name": company_name, | |
| "company_email": company_email, | |
| "inbox_thread_id": thread_id # Store thread ID so we know it's a reply and can send it in the same thread later | |
| } | |
| } | |
| } | |
| c_review.execute(''' | |
| INSERT INTO tracking (company_name, company_email, generated_subject, status, body_json) | |
| VALUES (?, ?, ?, 'pending', ?) | |
| ''', (company_name, company_email, new_subject, json.dumps(body_json_payload))) | |
| # 4. Update Inbox thread status | |
| c_inbox.execute("UPDATE inbox_threads SET status = 'drafted' WHERE id = ?", (inbox_id,)) | |
| conn_inbox.commit() | |
| conn_review.commit() | |
| print(json.dumps({"success": True})) | |
| except Exception as e: | |
| print(json.dumps({"error": str(e)})) | |
| if __name__ == "__main__": | |
| try: | |
| payload = json.loads(sys.stdin.read()) | |
| inbox_id = int(payload.get('inbox_id')) | |
| draft_reply(inbox_id) | |
| except Exception as e: | |
| print(json.dumps({"error": f"Invalid input: {e}"})) | |