ASSISTANT
Certainly! Below is a comprehensive **full prompt** designed to instruct the LLM to output a **single Python dictionary object with the requested keys**, followed by a **full, corrected Streamlit code** example that:
- Loads the JSON order file
- Sends it to the selected LLM with the prompt
- Parses the output dictionary
- Displays each main section in its own tab properly and cleanly
---
# 1. Full Prompt (Save as `order_prompt.txt` ideally)
```text
You are a customer service AI assistant specialized in summarizing detailed order JSON data for agents. Given the order JSON input, generate a comprehensive, clear, and structured summary split into the following sections exactly as described.
1. ORDER SUMMARY
Extract and display:
Order Number, Order Date, Current Status.
Total amount paid, merchandise total.
Billing and shipping customer details separately, including for each:
Full name
Full address (street, city, state, zip/postal code, country)
Phone number
Email address
2. SHIPMENT DETAILS
For each shipment, numbered in ascending order (Shipment #1, #2, etc.):
Shipment Number, Shipment Status, Delivery Method.
Expected delivery date and Actual delivery date (if available).
Line items with details:
Product name (include variant/options if present)
Quantity
Unit price
Total price (quantity x unit price or line total)
Tracking information, if present:
Carrier name
Tracking number
Latest status
Latest location (city/state or equivalent)
Delivery and gift wrap details (e.g., gift wrap requested, gift message) if any.
Payment details for that shipment extracted only from the shipment’s paymentSequences array:
List all payments for this shipment.
For each payment include (format accordingly):
Amount paid
Masked account number (show last 4 digits only, rest as asterisks)
Payment method (use the exact name from the paymentMethod field)
Payment plan type if present (e.g., DEFERRED)
Transaction type (e.g., Charge, Authorization)
Provide a sum of all payment amounts for this shipment.
If there is no paymentSequences array or it is empty, note “No payments recorded for this shipment.”
3. RETURN POLICY & ELIGIBILITY
For each line item or shipment (whichever the data applies to), provide:
Return eligibility status (True/False or Eligible/Not Eligible)
Return window date range(s) (start and end)
Any special return flags (e.g., virtual return, military return, blocked vendor)
Notes on refund or exchange restrictions (if any present)
If no return or eligibility data is available in the JSON, state so explicitly.
4. PAYMENT DETAILS
Process only the paymentSequences arrays within each shipment, do not combine or reference payments from other parts of the order JSON.
For EACH shipment, list all payments in ascending shipment order:
Payment amount
Masked account number
Payment method (or "Unknown" if missing)
Payment plan type if present
Transaction type
Total payments paid per shipment, and overall total paid across all shipments.
If any discrepancy exists between total payment sum for shipments versus total amounts paid in the order summary, include a clear note about this discrepancy.
Output the payment details grouped clearly by shipment number.
5. RECOMMENDED NEXT ACTIONS FOR AGENT
Identify likely customer questions based on order data.
For each question, provide:
Question: [Representative customer question phrased naturally]
Agent Script: [Empathetic, polite, and professional agent response referencing order details]
Include escalation triggers agents should watch for (examples):
- Shipment marked delivered but customer reports non-receipt.
- Customer requests a return but item/shipment is not eligible.
- Payment issues such as remaining balance or failed transaction.
- Reports of damaged, missing, or wrong items received.
- Gift wrap or registry concerns.
Include a short note advising when to escalate for each trigger.
6. PREDICTED CUSTOMER INTENT AND ANSWERS
Analyze the order JSON to predict customer intents/questions such as:
- Tracking or delivery status inquiry
- Return or refund requests
- Product issues (defect, damage, wrong item)
- Warranty inquiries
- Gift-related questions (gift wrap, gift message)
- Payment or billing inquiries
- Invoice or receipt copy requests
- Cancellation or order modification requests
For each predicted intent:
Intent: [Intent description/question]
Agent Script: [Concise, clear answer or note if no relevant info is available in the order data]
---
OUTPUT FORMAT:
Please output the entire detailed order summary as a single JSON-serializable Python dictionary object with these exact top-level keys:
- "Order Summary"
- "Shipments"
- "Return Policy & Eligibility"
- "Payment Details"
- "Recommended Next Actions for Agent"
- "Predicted Customer Intent and Answers"
Each value should be a well-structured dictionary or list, faithfully containing all relevant extracted data or notes as described above.
Ensure:
- All monetary values are formatted as strings with a dollar sign and two decimals, e.g. "$12.34".
- Mask all account numbers showing only last 4 digits, rest replaced with asterisks.
- Number shipments and payments in ascending order.
- Use booleans True/False or strings "Eligible"/"Not Eligible" for eligibility flags.
- If any section’s data is missing, explicitly include a suitable string such as "No data available".
- Do NOT include any explanatory text, headings, or markdown formatting in your output.
- Output ONLY the dictionary object (valid Python dict or JSON).
Example structure snippet:
{
"Order Summary": {
"Order Number": "123456789",
"Order Date": "2024-05-01",
"Current Status": "Shipped",
"Total Amount Paid": "$150.00",
"...": "..."
},
"Shipments": [
{
"Shipment Number": 1,
"Shipment Status": "Delivered",
"Delivery Method": "Standard Shipping",
"Expected Delivery Date": "2024-05-05",
"Actual Delivery Date": "2024-05-04",
"Line Items": [
{
"Product Name": "Blue Shirt – Size L",
"Quantity": 2,
"Unit Price": "$25.00",
"Total Price": "$50.00",
"Tracking Information": {
"Carrier Name": "FedEx",
"Tracking Number": "1234567890",
"Latest Status": "Delivered",
"Latest Location": "New York, NY"
},
"Gift Wrap": "Requested",
"Gift Message": "Happy Birthday"
}
],
"Payment Details": [
{
"Amount Paid": "$50.00",
"Masked Account Number": "************1234",
"Payment Method": "Visa",
"Payment Plan Type": "DEFERRED",
"Transaction Type": "Charge"
}
],
"Payment Total": "$50.00"
}
],
"...": "..."
}
Thank you.
```
---
# 2. Full Streamlit code
```python
import os
import json
import time
import re
import streamlit as st
from dotenv import load_dotenv
load_dotenv()
# Helper function to estimate tokens (for token tracking, optional)
def estimate_tokens(text: str) -> int:
return max(1, len(text) // 4)
# Gemini Client
try:
from google import genai
except ImportError:
genai = None
class GeminiClient:
def __init__(self):
self.project = "your-google-project-id"
self.location = "us-east4"
if not self.project:
raise ValueError("Set GOOGLE_CLOUD_PROJECT environment variable")
if genai is None:
raise ImportError("Please install google-generativeai package")
self.client = genai.Client(
vertexai=True,
project=self.project,
location=self.location,
)
self.model_name = "gemini-2.0-flash-001"
self.last_request_tokens = 0
self.last_response_tokens = 0
self.last_response_time = 0.0
def generate(self, system_prompt: str, user_content) -> str:
user_content_str = user_content if isinstance(user_content, str) else json.dumps(user_content, indent=2)
full_message = system_prompt + "\n\n" + user_content_str
self.last_request_tokens = estimate_tokens(full_message)
start_time = time.time()
response = self.client.models.generate_content(
model=self.model_name,
contents=full_message,
)
end_time = time.time()
self.last_response_time = end_time - start_time
parts_text = response.candidates[0].content.parts[0].text
text = "".join(parts_text) if isinstance(parts_text, list) else parts_text
self.last_response_tokens = estimate_tokens(text)
return text
# Azure OpenAI Client
from openai import AzureOpenAI
AZURE_OPENAI_ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT", "")
AZURE_OPENAI_KEY = os.getenv("AZURE_OPENAI_KEY", "")
AZURE_OPENAI_DEPLOYMENT = os.getenv("AZURE_OPENAI_DEPLOYMENT", "")
AZURE_OPENAI_API_VERSION = "2025-03-01-preview"
if not all([AZURE_OPENAI_ENDPOINT, AZURE_OPENAI_KEY, AZURE_OPENAI_DEPLOYMENT]):
raise ValueError("Azure OpenAI environment variables are not fully set")
openai_client = AzureOpenAI(
azure_endpoint=AZURE_OPENAI_ENDPOINT,
api_key=AZURE_OPENAI_KEY,
api_version=AZURE_OPENAI_API_VERSION,
)
class AzureClient:
def __init__(self):
self.model_name = AZURE_OPENAI_DEPLOYMENT
self.last_request_tokens = 0
self.last_response_tokens = 0
self.last_response_time = 0.0
def generate(self, system_prompt: str, user_content) -> str:
user_content_str = user_content if isinstance(user_content, str) else json.dumps(user_content, indent=2)
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_content_str},
]
prompt_text = system_prompt + "\n\n" + user_content_str
self.last_request_tokens = estimate_tokens(prompt_text)
start_time = time.time()
response = openai_client.chat.completions.create(
model=self.model_name,
messages=messages,
temperature=0,
)
end_time = time.time()
self.last_response_time = end_time - start_time
text = response.choices[0].message.content
self.last_response_tokens = estimate_tokens(text)
return text
def load_prompt(filename: str) -> str:
prompt_path = os.path.join(os.path.dirname(__file__), "prompts", filename)
if not os.path.isfile(prompt_path):
st.error(f"Prompt file not found at {prompt_path}")
return ""
with open(prompt_path, "r", encoding="utf-8") as f:
return f.read()
NOTES_PROMPT = load_prompt("note_prompt.txt")
ORDER_PROMPT = load_prompt("order_prompt.txt")
st.set_page_config("Macy's Order Analyzer", layout="wide")
st.title("📑 Macy's Order Analysis — Azure GPT & Vertex AI Gemini")
# Session State Initialization
if 'notes_data' not in st.session_state:
st.session_state.notes_data = None
if 'order_data' not in st.session_state:
st.session_state.order_data = None
if 'raw_json' not in st.session_state:
st.session_state.raw_json = None
uploaded_file = st.file_uploader("Upload Macy's JSON Order Data", type="json")
llm_option = st.selectbox(
"Choose LLM to use",
["azure", "gemini"],
format_func=lambda x: "Azure OpenAI GPT" if x == "azure" else "Vertex AI Gemini"
)
def generate_report(client, data, prompt_type: str):
try:
system_prompt = NOTES_PROMPT if prompt_type == "notes" else ORDER_PROMPT
text = client.generate(system_prompt=system_prompt, user_content=data)
return (
text,
client.model_name,
client.last_request_tokens,
client.last_response_tokens,
client.last_response_time,
)
except Exception as e:
return f"Error generating report: {str(e)}", None, 0, 0, 0
def safe_parse_dict(text: str):
try:
# First try JSON parsing
return json.loads(text)
except Exception:
import ast
try:
return ast.literal_eval(text)
except Exception:
return None
if uploaded_file:
try:
data = json.load(uploaded_file)
st.session_state.raw_json = data
# Reset previous results when new file is uploaded
st.session_state.notes_data = None
st.session_state.order_data = None
except json.JSONDecodeError:
st.error("❌ Invalid JSON file format")
data = None
if data:
col1, col2 = st.columns(2)
with col1:
if st.button("📝 Analyze Notes"):
with st.spinner("Analyzing notes..."):
try:
client = GeminiClient() if llm_option == "gemini" else AzureClient()
st.session_state.notes_data = generate_report(client, data, "notes")
except Exception as e:
st.error(f"❌ Notes analysis failed: {str(e)}")
with col2:
if st.button("📦 Generate Order Summary"):
with st.spinner("Generating order summary..."):
try:
client = GeminiClient() if llm_option == "gemini" else AzureClient()
st.session_state.order_data = generate_report(client, data, "order")
except Exception as e:
st.error(f"❌ Order summary failed: {str(e)}")
# Display results in tabs
tabs = []
if st.session_state.notes_data:
tabs.append("Notes Analysis")
if st.session_state.order_data:
tabs.append("Order Summary")
if tabs:
tab_objects = st.tabs(tabs)
for idx, tab_name in enumerate(tabs):
with tab_objects[idx]:
if tab_name == "Notes Analysis":
report = st.session_state.notes_data
if report[1]:
st.success(f"✅ Notes analysis using {report[1]}")
st.markdown(f"**Prompt tokens:** {report[2]} | **Response tokens:** {report[3]}")
st.markdown(f"**Processing time:** {report[4]:.2f}s")
st.markdown("---")
st.markdown(report[0])
else:
st.error(report[0])
elif tab_name == "Order Summary":
report = st.session_state.order_data
if report[1]:
st.success(f"✅ Order summary using {report[1]}")
st.markdown(f"**Prompt tokens:** {report[2]} | **Response tokens:** {report[3]}")
st.markdown(f"**Processing time:** {report[4]:.2f}s")
st.markdown("---")
order_dict = safe_parse_dict(report[0])
if order_dict is None:
st.error("Failed to parse LLM output into dictionary.")
else:
# Use top-level keys as main tabs
main_tabs = st.tabs(list(order_dict.keys()))
for i, key in enumerate(order_dict.keys()):
with main_tabs[i]:
content = order_dict[key]
# Handle Order Summary: dictionary, print key-values
if key == "Order Summary":
if isinstance(content, dict):
for k_, v_ in content.items():
if isinstance(v_, dict):
st.markdown(f"**{k_}:**")
for subk, subv in v_.items():
st.markdown(f"- {subk}: {subv}")
else:
st.markdown(f"**{k_}:** {v_}")
else:
st.markdown(str(content))
# Shipments: list of shipments
elif key == "Shipments":
if isinstance(content, list):
for shipment in content:
st.markdown(f"### Shipment #{shipment.get('Shipment Number', '')}")
for sk, sv in shipment.items():
if sk == "Line Items" and isinstance(sv, list):
st.markdown("**Line Items:**")
for item in sv:
item_lines = [f"- {ik}: {iv}" for ik, iv in item.items()]
st.markdown("\n".join(item_lines))
elif sk == "Payment Details" and isinstance(sv, list):
st.markdown("**Payments for this shipment:**")
for payment in sv:
payment_lines = [f"- {pk}: {pv}" for pk, pv in payment.items()]
st.markdown("\n".join(payment_lines))
else:
if sk != "Shipment Number": # Already in title
st.markdown(f"**{sk}:** {sv}")
else:
st.markdown(str(content))
# Return Policy & Eligibility: might be dict or string
elif key == "Return Policy & Eligibility":
if isinstance(content, dict):
for k_, v_ in content.items():
st.markdown(f"- **{k_}:** {v_}")
elif isinstance(content, list):
for item in content:
if isinstance(item, dict):
lines = [f"- {k}: {v}" for k,v in item.items()]
st.markdown("\n".join(lines))
else:
st.markdown(f"- {item}")
else:
st.markdown(str(content))
# Payment Details: dict or list
elif key == "Payment Details":
if isinstance(content, dict):
for shipment_num, payments_list in content.items():
st.markdown(f"### Payment details for Shipment {shipment_num}")
if isinstance(payments_list, list):
for payment in payments_list:
lines = [f"- {k}: {v}" for k, v in payment.items()]
st.markdown("\n".join(lines))
else:
st.markdown(str(payments_list))
elif isinstance(content, list):
for payment in content:
if isinstance(payment, dict):
lines = [f"- {k}: {v}" for k, v in payment.items()]
st.markdown("\n".join(lines))
else:
st.markdown(str(payment))
else:
st.markdown(str(content))
# Recommended Next Actions for Agent
elif key == "Recommended Next Actions for Agent":
if isinstance(content, list):
for item in content:
if isinstance(item, dict):
# Show Questions and Agent Script clearly
question = item.get("Question", "")
agent_script = item.get("Agent Script", "")
st.markdown(f"**Question:** {question}")
st.markdown(f"**Agent Script:** {agent_script}")
st.markdown("---")
else:
st.markdown(str(item))
else:
st.markdown(str(content))
# Predicted Customer Intent and Answers
elif key == "Predicted Customer Intent and Answers":
if isinstance(content, list):
for item in content:
if isinstance(item, dict):
intent = item.get("Intent", "")
agent_script = item.get("Agent Script", "")
st.markdown(f"**Intent:** {intent}")
st.markdown(f"**Agent Script:** {agent_script}")
st.markdown("---")
else:
st.markdown(str(item))
else:
st.markdown(str(content))
else:
# Generic fallback display
st.markdown(str(content))
else:
st.error(report[0])
if uploaded_file is None:
st.info("Please upload a Macy's JSON order file to begin analysis.")
if uploaded_file and st.checkbox("Show raw JSON data"):
if st.session_state.raw_json:
st.json(st.session_state.raw_json)
else:
st.warning("No JSON loaded.")
```
---
### Notes to set up and run:
- Put the **prompt text above** in a file named `order_prompt.txt` inside a `prompts` folder next to your app Python script.
- Set your environment variables for Azure or Google credentials as needed.
- Adjust the Google Project ID placeholder (`your-google-project-id`) in `GeminiClient` class to your real project.
- Run with `streamlit run yourscript.py` after installing dependencies (`streamlit`, `python-dotenv`, `google-generativeai`, `openai`).
---
# Summary
- The prompt **forces the LLM to output one structured dictionary object only** with exact keys.
- The Streamlit app **parses LLM output as dictionary** and displays each section in tabs cleanly, handling lists/dicts gracefully.
- No regex splitting is needed; this approach is robust and maintainable.
---
If you want me to help build a sample order JSON or test this locally, let me know!