SSSSSSSiao commited on
Commit
c1bc92f
·
verified ·
1 Parent(s): 45d6734

Update app.py

Browse files

Make prep list and replies deterministic

Files changed (1) hide show
  1. app.py +94 -41
app.py CHANGED
@@ -4,7 +4,6 @@ import gradio as gr
4
  import torch
5
  from transformers import AutoModelForCausalLM, AutoTokenizer
6
 
7
- # MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct"
8
  MODEL_ID = "Qwen/Qwen2.5-1.5B-Instruct"
9
 
10
  ORDER_COLUMNS = [
@@ -23,32 +22,6 @@ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
23
  model = AutoModelForCausalLM.from_pretrained(MODEL_ID, torch_dtype=torch.float32)
24
  model.eval()
25
 
26
- # SYSTEM_PROMPT = """
27
- # You extract customer orders from messy DMs for tiny sellers.
28
- # Return only valid JSON with this exact shape:
29
- # {
30
- # "orders": [
31
- # {
32
- # "customer": "",
33
- # "item": "",
34
- # "quantity": "",
35
- # "flavor": "",
36
- # "pickup_time": "",
37
- # "delivery_address": "",
38
- # "payment_status": "",
39
- # "notes": "",
40
- # "missing_fields": []
41
- # }
42
- # ],
43
- # "prep_list": [],
44
- # "reply_drafts": [
45
- # {"customer": "", "reply": ""}
46
- # ]
47
- # }
48
- # Use empty strings for unknown values. Put missing details in missing_fields.
49
- # """
50
-
51
-
52
 
53
  SYSTEM_PROMPT = """
54
  You are a careful order extraction engine for tiny sellers.
@@ -69,25 +42,26 @@ Extract customer orders from messy DMs. Return only valid JSON with this exact s
69
  }
70
  ],
71
  "prep_list": [],
72
- "reply_drafts": [
73
- {"customer": "", "reply": ""}
74
- ]
75
  }
76
 
77
  Critical rules:
78
- - Do not invent customer names.
79
- - Do not change customer names.
80
- - Do not merge different customers.
 
81
  - Include every customer message that looks like an order or possible order.
82
- - Use only facts explicitly present in the messages.
83
  - If a value is unknown, use an empty string.
84
- - Do not add order_id or total_cost unless the message mentions them.
85
- - For pickup orders, put the pickup time in pickup_time and leave delivery_address empty unless a real address is given.
86
- - If the customer is unsure, still include the order and put uncertainty in notes.
87
- - missing_fields should only include practical fields the seller needs to ask for, such as quantity, flavor, pickup_time, delivery_address, or payment_status.
88
- - Reply drafts should be short, friendly, and ask only for missing information.
 
89
  """
90
 
 
91
  EXAMPLE_INPUT = """Maya: Hi! Can I get 2 dozen cupcakes for Saturday morning? Half vanilla, half chocolate.
92
  Sam: Need 1 birthday cake, chocolate, for pickup Friday 5pm. I can pay Venmo.
93
  Lena: Do you still have lemon bars? I need some for tomorrow but not sure how many yet.
@@ -134,6 +108,79 @@ def format_replies(replies):
134
  lines.append(f"**{customer}**\n\n{text}")
135
  return "### Reply drafts\n\n" + "\n\n---\n\n".join(lines)
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  def analyze_messages(messages):
138
  if not messages.strip():
139
  return pd.DataFrame(columns=ORDER_COLUMNS), "Paste some DMs first.", "", ""
@@ -172,8 +219,14 @@ def analyze_messages(messages):
172
  )
173
 
174
  orders_df = normalize_orders(data)
175
- prep = format_list("Prep list", data.get("prep_list", []))
176
- replies = format_replies(data.get("reply_drafts", []))
 
 
 
 
 
 
177
  raw = json.dumps(data, indent=2, ensure_ascii=False)
178
  return orders_df, prep, replies, raw
179
 
 
4
  import torch
5
  from transformers import AutoModelForCausalLM, AutoTokenizer
6
 
 
7
  MODEL_ID = "Qwen/Qwen2.5-1.5B-Instruct"
8
 
9
  ORDER_COLUMNS = [
 
22
  model = AutoModelForCausalLM.from_pretrained(MODEL_ID, torch_dtype=torch.float32)
23
  model.eval()
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  SYSTEM_PROMPT = """
27
  You are a careful order extraction engine for tiny sellers.
 
42
  }
43
  ],
44
  "prep_list": [],
45
+ "reply_drafts": []
 
 
46
  }
47
 
48
  Critical rules:
49
+ - Treat each line as one separate customer message.
50
+ - The text before the first ":" is the customer name.
51
+ - Copy customer names exactly as written. Do not uppercase or lowercase them.
52
+ - Never copy details from one customer's message into another customer's order.
53
  - Include every customer message that looks like an order or possible order.
54
+ - Use only facts explicitly present in that customer's own message.
55
  - If a value is unknown, use an empty string.
56
+ - Do not add order_id or total_cost.
57
+ - For pickup orders, put pickup time in pickup_time. Put a pickup place or delivery address in delivery_address.
58
+ - If the customer is unsure, still include the order and describe the uncertainty in notes.
59
+ - missing_fields should only include fields the seller needs to ask for: quantity, flavor, pickup_time, delivery_address, payment_status.
60
+ - Always set prep_list to [].
61
+ - Always set reply_drafts to [].
62
  """
63
 
64
+
65
  EXAMPLE_INPUT = """Maya: Hi! Can I get 2 dozen cupcakes for Saturday morning? Half vanilla, half chocolate.
66
  Sam: Need 1 birthday cake, chocolate, for pickup Friday 5pm. I can pay Venmo.
67
  Lena: Do you still have lemon bars? I need some for tomorrow but not sure how many yet.
 
108
  lines.append(f"**{customer}**\n\n{text}")
109
  return "### Reply drafts\n\n" + "\n\n---\n\n".join(lines)
110
 
111
+ def text_value(value):
112
+ if isinstance(value, list):
113
+ return ", ".join(str(v) for v in value if str(v).strip())
114
+ if value is None:
115
+ return ""
116
+ return str(value).strip()
117
+
118
+ def missing_list(order):
119
+ raw = order.get("missing_fields", [])
120
+ if isinstance(raw, str):
121
+ fields = [part.strip() for part in raw.split(",") if part.strip()]
122
+ else:
123
+ fields = [str(part).strip() for part in raw if str(part).strip()]
124
+
125
+ item = text_value(order.get("item"))
126
+ if item and not text_value(order.get("quantity")):
127
+ fields.append("quantity")
128
+ if item and not text_value(order.get("pickup_time")) and not text_value(order.get("delivery_address")):
129
+ fields.append("pickup_time")
130
+ if item and not text_value(order.get("payment_status")):
131
+ fields.append("payment_status")
132
+
133
+ return sorted(set(fields))
134
+
135
+ def build_prep_list(data):
136
+ items = []
137
+ for order in data.get("orders", []):
138
+ item = text_value(order.get("item"))
139
+ if not item:
140
+ continue
141
+
142
+ customer = text_value(order.get("customer")) or "customer"
143
+ quantity = text_value(order.get("quantity")) or "quantity to confirm"
144
+ flavor = text_value(order.get("flavor"))
145
+
146
+ line = f"{quantity} {item}"
147
+ if flavor:
148
+ line += f" ({flavor})"
149
+ line += f" - {customer}"
150
+ items.append(line)
151
+
152
+ return items
153
+
154
+ def build_reply_drafts(data):
155
+ replies = []
156
+ labels = {
157
+ "quantity": "quantity",
158
+ "flavor": "flavor",
159
+ "pickup_time": "pickup or delivery time",
160
+ "delivery_address": "pickup place or delivery address",
161
+ "payment_status": "payment status",
162
+ }
163
+
164
+ for order in data.get("orders", []):
165
+ customer = text_value(order.get("customer")) or "there"
166
+ item = text_value(order.get("item")) or "order"
167
+ quantity = text_value(order.get("quantity"))
168
+ flavor = text_value(order.get("flavor"))
169
+ missing = [labels.get(field, field) for field in missing_list(order)]
170
+
171
+ if missing:
172
+ needed = ", ".join(missing)
173
+ reply = f"Thanks, {customer}! I have your {item} order. Could you confirm the {needed}?"
174
+ else:
175
+ summary = f"{quantity} {item}".strip()
176
+ if flavor:
177
+ summary += f" ({flavor})"
178
+ reply = f"Thanks, {customer}! Confirming your order: {summary}."
179
+
180
+ replies.append({"customer": customer, "reply": reply})
181
+
182
+ return replies
183
+
184
  def analyze_messages(messages):
185
  if not messages.strip():
186
  return pd.DataFrame(columns=ORDER_COLUMNS), "Paste some DMs first.", "", ""
 
219
  )
220
 
221
  orders_df = normalize_orders(data)
222
+ auto_prep = build_prep_list(data)
223
+ auto_replies = build_reply_drafts(data)
224
+
225
+ data["prep_list"] = auto_prep
226
+ data["reply_drafts"] = auto_replies
227
+
228
+ prep = format_list("Prep list", auto_prep)
229
+ replies = format_replies(auto_replies)
230
  raw = json.dumps(data, indent=2, ensure_ascii=False)
231
  return orders_df, prep, replies, raw
232