vachaspathi commited on
Commit
5a38a8f
·
verified ·
1 Parent(s): d3333ba

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -43
app.py CHANGED
@@ -6,12 +6,9 @@ import requests
6
  import os
7
  import gradio as gr
8
  import json
9
- import time
10
  import re
11
  import logging
12
- import asyncio
13
  import gc
14
- import shutil
15
 
16
  # --- Import OCR Engine & Prompts ---
17
  try:
@@ -20,7 +17,7 @@ try:
20
  except ImportError:
21
  def extract_text_from_file(path): return ""
22
  def get_ocr_extraction_prompt(txt): return txt
23
- def get_agent_prompt(h, c, u): return u
24
 
25
  logging.basicConfig(level=logging.INFO)
26
  logger = logging.getLogger("mcp_server")
@@ -83,12 +80,11 @@ def local_llm_generate(prompt: str, max_tokens: int = 512) -> Dict[str, Any]:
83
  return {"text": "Model not loaded.", "raw": None}
84
 
85
  try:
86
- # FIX: Removed invalid flags 'temperature', 'top_p', etc. when do_sample is False
87
  out = LLM_PIPELINE(
88
  prompt,
89
  max_new_tokens=max_tokens,
90
  return_full_text=False,
91
- do_sample=False # Deterministic
92
  )
93
  text = out[0]["generated_text"] if out else ""
94
  return {"text": text, "raw": out}
@@ -113,7 +109,7 @@ def create_record(module_name: str, record_data: dict) -> str:
113
  if r.status_code in (200, 201):
114
  try:
115
  d = r.json().get("data", [{}])[0].get("details", {})
116
- return json.dumps({"status": "success", "id": d.get("id"), "response": r.json()})
117
  except:
118
  return json.dumps(r.json())
119
  return r.text
@@ -129,7 +125,6 @@ def create_invoice(data: dict) -> str:
129
  @mcp.tool()
130
  def process_document(file_path: str, target_module: Optional[str] = "Contacts") -> dict:
131
  if not os.path.exists(file_path):
132
- logger.error(f"process_document: File not found at {file_path}")
133
  return {"error": f"File not found at path: {file_path}"}
134
 
135
  # 1. OCR
@@ -163,7 +158,7 @@ def parse_and_execute(model_text: str, history: list) -> str:
163
  args = _normalize_local_path_args(cmd.get("args", {}))
164
 
165
  if tool == "create_record":
166
- res = create_record(args.get("module", "Contacts"), args)
167
  results.append(f"Record: {res}")
168
  try:
169
  rj = json.loads(res)
@@ -172,57 +167,56 @@ def parse_and_execute(model_text: str, history: list) -> str:
172
  except: pass
173
 
174
  elif tool == "create_invoice":
 
175
  if not args.get("customer_id") and last_contact_id:
176
  args["customer_id"] = last_contact_id
177
 
178
- items = []
179
- for it in args.get("line_items", []):
180
- items.append({
181
- "name": it.get("name", "Item"),
182
- "rate": float(str(it.get("rate", 0)).replace("$", "")),
183
- "quantity": int(it.get("quantity", 1))
184
- })
185
-
186
- payload = {"customer_id": args.get("customer_id"), "line_items": items}
187
- if args.get("currency"): payload["currency_code"] = args["currency"]
188
-
189
- res = create_invoice(payload)
190
- results.append(f"Invoice: {res}")
191
 
192
- elif tool == "process_document":
193
- # NOTE: Prompts try to prevent this, but if it happens, we rely on args being correct
194
- res = process_document(args.get("file_path"))
195
- results.append(f"Processed: {res}")
196
 
197
  return "\n".join(results)
198
 
199
  # --- Chat Core ---
200
  def chat_logic(message: str, file_path: str, history: list) -> str:
201
 
202
- # 1. Ingest File IMMEDIATELY
203
- file_context = ""
204
  if file_path:
205
- logger.info(f"Ingesting file from path: {file_path}")
206
  doc = process_document(file_path)
 
207
  if doc.get("status") == "success":
208
- file_context = json.dumps(doc["extracted_data"])
209
- if not message: message = "Create records from this file."
 
 
 
 
 
 
210
  else:
211
- return f"OCR Failed: {doc}"
212
 
213
- # 2. Decision Prompt (With context injected)
214
  hist_txt = "\n".join([f"U: {h[0]}\nA: {h[1]}" for h in history])
215
- prompt = get_agent_prompt(hist_txt, file_context, message)
216
 
217
- # 3. Gen & Execute
218
- gen = local_llm_generate(prompt, max_tokens=200)
 
 
219
  logger.info(f"LLM Decision: {gen['text']}")
220
 
221
  tool_data = extract_json_safely(gen["text"])
222
 
223
  if tool_data:
 
224
  return parse_and_execute(gen["text"], history)
225
 
 
226
  return gen["text"]
227
 
228
  # --- UI ---
@@ -231,13 +225,6 @@ def chat_handler(msg, hist):
231
  files = msg.get("files", [])
232
  path = files[0] if files else None
233
 
234
- if path:
235
- logger.info(f"UI received file: {path}")
236
-
237
- # Direct path bypass for debugging
238
- if not path and txt.startswith("/mnt/data"):
239
- return str(process_document(txt))
240
-
241
  return chat_logic(txt, path, hist)
242
 
243
  if __name__ == "__main__":
 
6
  import os
7
  import gradio as gr
8
  import json
 
9
  import re
10
  import logging
 
11
  import gc
 
12
 
13
  # --- Import OCR Engine & Prompts ---
14
  try:
 
17
  except ImportError:
18
  def extract_text_from_file(path): return ""
19
  def get_ocr_extraction_prompt(txt): return txt
20
+ def get_agent_prompt(h, u): return u
21
 
22
  logging.basicConfig(level=logging.INFO)
23
  logger = logging.getLogger("mcp_server")
 
80
  return {"text": "Model not loaded.", "raw": None}
81
 
82
  try:
 
83
  out = LLM_PIPELINE(
84
  prompt,
85
  max_new_tokens=max_tokens,
86
  return_full_text=False,
87
+ do_sample=False
88
  )
89
  text = out[0]["generated_text"] if out else ""
90
  return {"text": text, "raw": out}
 
109
  if r.status_code in (200, 201):
110
  try:
111
  d = r.json().get("data", [{}])[0].get("details", {})
112
+ return json.dumps({"status": "success", "id": d.get("id"), "zoho_response": r.json()})
113
  except:
114
  return json.dumps(r.json())
115
  return r.text
 
125
  @mcp.tool()
126
  def process_document(file_path: str, target_module: Optional[str] = "Contacts") -> dict:
127
  if not os.path.exists(file_path):
 
128
  return {"error": f"File not found at path: {file_path}"}
129
 
130
  # 1. OCR
 
158
  args = _normalize_local_path_args(cmd.get("args", {}))
159
 
160
  if tool == "create_record":
161
+ res = create_record(args.get("module_name", "Contacts"), args.get("record_data", {}))
162
  results.append(f"Record: {res}")
163
  try:
164
  rj = json.loads(res)
 
167
  except: pass
168
 
169
  elif tool == "create_invoice":
170
+ # Auto-fill contact_id if we just created one
171
  if not args.get("customer_id") and last_contact_id:
172
  args["customer_id"] = last_contact_id
173
 
174
+ # Map Items from strict structure
175
+ invoice_payload = args # Assuming LLM passes correct structure, or map here
176
+ if last_contact_id and "customer_id" not in invoice_payload:
177
+ invoice_payload["customer_id"] = last_contact_id
 
 
 
 
 
 
 
 
 
178
 
179
+ res = create_invoice(invoice_payload)
180
+ results.append(f"Invoice: {res}")
 
 
181
 
182
  return "\n".join(results)
183
 
184
  # --- Chat Core ---
185
  def chat_logic(message: str, file_path: str, history: list) -> str:
186
 
187
+ # PHASE 1: File Upload -> Extraction Only (No Zoho Auth yet)
 
188
  if file_path:
189
+ logger.info(f"Processing file: {file_path}")
190
  doc = process_document(file_path)
191
+
192
  if doc.get("status") == "success":
193
+ extracted_json = json.dumps(doc["extracted_data"], indent=2)
194
+ # We return this text. It gets added to history.
195
+ # The User must then say "Yes, push it" to trigger Phase 2.
196
+ return (
197
+ f"I extracted the following data from **{doc['file']}**:\n\n"
198
+ f"```json\n{extracted_json}\n```\n\n"
199
+ "Please review it. If it looks correct, type **'Create Invoice'** or **'Push to Zoho'**."
200
+ )
201
  else:
202
+ return f"OCR Failed: {doc.get('error')}"
203
 
204
+ # PHASE 2: Text Interaction (Check History for JSON + Intent)
205
  hist_txt = "\n".join([f"U: {h[0]}\nA: {h[1]}" for h in history])
 
206
 
207
+ # The Prompt now checks history for JSON and waits for explicit "save/push" keywords
208
+ prompt = get_agent_prompt(hist_txt, message)
209
+
210
+ gen = local_llm_generate(prompt, max_tokens=256)
211
  logger.info(f"LLM Decision: {gen['text']}")
212
 
213
  tool_data = extract_json_safely(gen["text"])
214
 
215
  if tool_data:
216
+ # User confirmed -> Execute Tool (Triggers Zoho Auth)
217
  return parse_and_execute(gen["text"], history)
218
 
219
+ # Just chat/clarification
220
  return gen["text"]
221
 
222
  # --- UI ---
 
225
  files = msg.get("files", [])
226
  path = files[0] if files else None
227
 
 
 
 
 
 
 
 
228
  return chat_logic(txt, path, hist)
229
 
230
  if __name__ == "__main__":