Update utility.py
Browse files- utility.py +77 -56
utility.py
CHANGED
|
@@ -1172,7 +1172,16 @@ def read_datalake(user_phone: str, query: str) -> str:
|
|
| 1172 |
)
|
| 1173 |
|
| 1174 |
datalake_dfs = [df for _, df in all_dfs_with_names]
|
| 1175 |
-
lake = SmartDatalake(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1176 |
|
| 1177 |
response = lake.chat(pandasai_prompt)
|
| 1178 |
|
|
@@ -1183,62 +1192,73 @@ def read_datalake(user_phone: str, query: str) -> str:
|
|
| 1183 |
else:
|
| 1184 |
return str(response)
|
| 1185 |
|
| 1186 |
-
except (NoCodeFoundError, MaliciousQueryError) as e:
|
| 1187 |
-
logger.info(f"PandasAI found no code for '{query}' (Error: {type(e).__name__}). Routing to Business Coach as fallback.")
|
| 1188 |
-
snapshot = engine.generate_business_snapshot()
|
| 1189 |
-
snapshot_str = json.dumps(snapshot, indent=2)
|
| 1190 |
-
|
| 1191 |
-
synthesis_prompt = f"""
|
| 1192 |
-
You are Qx, a friendly and insightful business coach and financial expert. The user is asking a general question. Only perform calculations when necessary. Your task is to provide a clear, helpful, and strategic answer based on their question, using your general knowledge and the business snapshot provided below for context.
|
| 1193 |
-
|
| 1194 |
-
**IMPORTANT RULES:**
|
| 1195 |
-
1. **Use the Context:** Use the Business Snapshot as your internal knowledge to make your advice relevant and personalized. For example, if inventory is high for an item, you might suggest a promotion. If profit is low, you might suggest cost-cutting measures.
|
| 1196 |
-
2. **You can state the numbers, info or metrics from the data where helpful. Synthesize them into your advice. generate insight from the data if needed.
|
| 1197 |
-
3. **Stay in Character:** Act as a coach. Be encouraging and provide actionable advice.
|
| 1198 |
-
4. **Handle 'Help' Queries:** If asked about your capabilities, explain that you can record transactions (sales, expenses, etc.) via text or images, generate detailed reports (profit, sales by item), answer questions about their data, and provide business advice.
|
| 1199 |
-
5. **Format for WhatsApp:** Use *bold*, _italic_, and emojis to make your response clear and engaging.
|
| 1200 |
-
|
| 1201 |
-
**BUSINESS SNAPSHOT (INTERNAL CONTEXT ONLY):**
|
| 1202 |
-
{snapshot_str}
|
| 1203 |
-
|
| 1204 |
-
**User's Question:**
|
| 1205 |
-
"{query}"
|
| 1206 |
-
"""
|
| 1207 |
-
try:
|
| 1208 |
-
response = llm.invoke(synthesis_prompt)
|
| 1209 |
-
return response.content
|
| 1210 |
-
except Exception as llm_error:
|
| 1211 |
-
logger.error(f"Business coach LLM failed for query '{query}': {llm_error}", exc_info=True)
|
| 1212 |
-
return "I'm here to help with your business questions, but I'm having trouble processing your request right now. Could you try rephrasing your question?"
|
| 1213 |
-
|
| 1214 |
except Exception as e:
|
| 1215 |
-
|
| 1216 |
-
#
|
| 1217 |
-
|
| 1218 |
-
|
| 1219 |
-
|
| 1220 |
-
|
| 1221 |
-
|
| 1222 |
-
|
| 1223 |
-
|
| 1224 |
-
|
| 1225 |
-
|
| 1226 |
-
|
| 1227 |
-
|
| 1228 |
-
|
| 1229 |
-
|
| 1230 |
-
|
| 1231 |
-
|
| 1232 |
-
|
| 1233 |
-
|
| 1234 |
-
|
| 1235 |
-
|
| 1236 |
-
|
| 1237 |
-
|
| 1238 |
-
|
| 1239 |
-
|
| 1240 |
-
|
| 1241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1242 |
|
| 1243 |
except Exception as e:
|
| 1244 |
logger.error(f"Data query failed for user {user_phone}, query '{query}': {e}", exc_info=True)
|
|
@@ -1272,6 +1292,7 @@ def read_datalake(user_phone: str, query: str) -> str:
|
|
| 1272 |
return "I'm here to help with your business questions, but I'm experiencing technical difficulties right now. Please try again in a moment."
|
| 1273 |
|
| 1274 |
|
|
|
|
| 1275 |
def _find_document_by_details(user_phone: str, collection_name: str, details: Dict) -> Optional[Any]:
|
| 1276 |
col_ref = db.collection("users").document(user_phone).collection(collection_name)
|
| 1277 |
if 'transaction_id' in details and details['transaction_id']:
|
|
|
|
| 1172 |
)
|
| 1173 |
|
| 1174 |
datalake_dfs = [df for _, df in all_dfs_with_names]
|
| 1175 |
+
lake = SmartDatalake(
|
| 1176 |
+
datalake_dfs,
|
| 1177 |
+
config={
|
| 1178 |
+
"llm": llm,
|
| 1179 |
+
"response_parser": FlaskResponse,
|
| 1180 |
+
"save_charts_path": user_defined_path,
|
| 1181 |
+
"enable_cache": False,
|
| 1182 |
+
"conversational": False
|
| 1183 |
+
}
|
| 1184 |
+
)
|
| 1185 |
|
| 1186 |
response = lake.chat(pandasai_prompt)
|
| 1187 |
|
|
|
|
| 1192 |
else:
|
| 1193 |
return str(response)
|
| 1194 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1195 |
except Exception as e:
|
| 1196 |
+
# Unified handler: catch PandasAI edge-cases by CLASS NAME or MESSAGE,
|
| 1197 |
+
# then route to the Business Coach fallback.
|
| 1198 |
+
err_name = e.__class__.__name__
|
| 1199 |
+
err_msg = str(e)
|
| 1200 |
+
is_pandasai_no_code = (
|
| 1201 |
+
err_name in ("NoCodeFoundError", "MaliciousQueryError")
|
| 1202 |
+
or "No code found" in err_msg
|
| 1203 |
+
or "NoCodeFoundError" in err_name
|
| 1204 |
+
or "MaliciousQueryError" in err_name
|
| 1205 |
+
)
|
| 1206 |
+
|
| 1207 |
+
if is_pandasai_no_code:
|
| 1208 |
+
logger.info(f"PandasAI found no code for '{query}' (Error: {err_name}). Routing to Business Coach as fallback.")
|
| 1209 |
+
snapshot = engine.generate_business_snapshot()
|
| 1210 |
+
snapshot_str = json.dumps(snapshot, indent=2)
|
| 1211 |
+
|
| 1212 |
+
synthesis_prompt = f"""
|
| 1213 |
+
You are Qx, a friendly and insightful business coach and financial expert. The user is asking a general question. Only perform calculations when necessary. Your task is to provide a clear, helpful, and strategic answer based on their question, using your general knowledge and the business snapshot provided below for context.
|
| 1214 |
+
|
| 1215 |
+
**IMPORTANT RULES:**
|
| 1216 |
+
1. **Use the Context:** Use the Business Snapshot as your internal knowledge to make your advice relevant and personalized. For example, if inventory is high for an item, you might suggest a promotion. If profit is low, you might suggest cost-cutting measures.
|
| 1217 |
+
2. **You can state the numbers, info or metrics from the data where helpful. Synthesize them into your advice. generate insight from the data if needed.
|
| 1218 |
+
3. **Stay in Character:** Act as a coach. Be encouraging and provide actionable advice.
|
| 1219 |
+
4. **Handle 'Help' Queries:** If asked about your capabilities, explain that you can record transactions (sales, expenses, etc.) via text or images, generate detailed reports (profit, sales by item), answer questions about their data, and provide business advice.
|
| 1220 |
+
5. **Format for WhatsApp:** Use *bold*, _italic_, and emojis to make your response clear and engaging.
|
| 1221 |
+
|
| 1222 |
+
**BUSINESS SNAPSHOT (INTERNAL CONTEXT ONLY):**
|
| 1223 |
+
{snapshot_str}
|
| 1224 |
+
|
| 1225 |
+
**User's Question:**
|
| 1226 |
+
"{query}"
|
| 1227 |
+
"""
|
| 1228 |
+
try:
|
| 1229 |
+
response = llm.invoke(synthesis_prompt)
|
| 1230 |
+
return response.content
|
| 1231 |
+
except Exception as llm_error:
|
| 1232 |
+
logger.error(f"Business coach LLM failed for query '{query}': {llm_error}", exc_info=True)
|
| 1233 |
+
return "I'm here to help with your business questions, but I'm having trouble processing your request right now. Could you try rephrasing your question?"
|
| 1234 |
+
else:
|
| 1235 |
+
logger.warning(f"PandasAI failed for query '{query}' with error: {e}. Falling back to Business Coach.")
|
| 1236 |
+
# Route ANY other PandasAI exception to the business coach
|
| 1237 |
+
snapshot = engine.generate_business_snapshot()
|
| 1238 |
+
snapshot_str = json.dumps(snapshot, indent=2)
|
| 1239 |
+
|
| 1240 |
+
synthesis_prompt = f"""
|
| 1241 |
+
You are Qx, a friendly and insightful business coach and financial expert. The user is asking a general question. Only perform calculations when necessary. Your task is to provide a clear, helpful, and strategic answer based on their question, using your general knowledge and the business snapshot provided below for context.
|
| 1242 |
+
|
| 1243 |
+
**IMPORTANT RULES:**
|
| 1244 |
+
1. **Use the Context:** Use the Business Snapshot as your internal knowledge to make your advice relevant and personalized. For example, if inventory is high for an item, you might suggest a promotion. If profit is low, you might suggest cost-cutting measures.
|
| 1245 |
+
2. **You can state the numbers, info or metrics from the data where helpful. Synthesize them into your advice. generate insight from the data if needed.
|
| 1246 |
+
3. **Stay in Character:** Act as a coach. Be encouraging and provide actionable advice.
|
| 1247 |
+
4. **Handle 'Help' Queries:** If asked about your capabilities, explain that you can record transactions (sales, expenses, etc.) via text or images, generate detailed reports (profit, sales by item), answer questions about their data, and provide business advice.
|
| 1248 |
+
5. **Format for WhatsApp:** Use *bold*, _italic_, and emojis to make your response clear and engaging.
|
| 1249 |
+
|
| 1250 |
+
**BUSINESS SNAPSHOT (INTERNAL CONTEXT ONLY):**
|
| 1251 |
+
{snapshot_str}
|
| 1252 |
+
|
| 1253 |
+
**User's Question:**
|
| 1254 |
+
"{query}"
|
| 1255 |
+
"""
|
| 1256 |
+
try:
|
| 1257 |
+
response = llm.invoke(synthesis_prompt)
|
| 1258 |
+
return response.content
|
| 1259 |
+
except Exception as llm_error:
|
| 1260 |
+
logger.error(f"Business coach LLM failed for query '{query}': {llm_error}", exc_info=True)
|
| 1261 |
+
return "I'm here to help with your business questions, but I'm having trouble processing your request right now. Could you try rephrasing your question?"
|
| 1262 |
|
| 1263 |
except Exception as e:
|
| 1264 |
logger.error(f"Data query failed for user {user_phone}, query '{query}': {e}", exc_info=True)
|
|
|
|
| 1292 |
return "I'm here to help with your business questions, but I'm experiencing technical difficulties right now. Please try again in a moment."
|
| 1293 |
|
| 1294 |
|
| 1295 |
+
|
| 1296 |
def _find_document_by_details(user_phone: str, collection_name: str, details: Dict) -> Optional[Any]:
|
| 1297 |
col_ref = db.collection("users").document(user_phone).collection(collection_name)
|
| 1298 |
if 'transaction_id' in details and details['transaction_id']:
|