Seth0330 commited on
Commit
e613cc6
·
verified ·
1 Parent(s): 7a3cbf5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -48
app.py CHANGED
@@ -7,12 +7,10 @@ import time
7
  import mimetypes
8
  import pandas as pd
9
 
10
- # LangChain & LangGraph
11
  from langchain_community.chat_models import ChatOpenAI
12
- from langgraph.graph import StateGraph, END
13
- from langgraph.prebuilt import create_react_agent
14
 
15
- st.set_page_config(page_title="PDF Tools", layout="wide")
16
 
17
  # -------- LLM Model Setup --------
18
  MODELS = {
@@ -254,7 +252,7 @@ def extract_text_from_unstract(uploaded_file):
254
  except Exception:
255
  return r.text
256
 
257
- # --------- NEW: UPLOAD PO CSV ---------
258
  st.sidebar.header("Step 1: Upload Active Purchase Orders (POs)")
259
  po_file = st.sidebar.file_uploader(
260
  "Upload POs CSV (must include PO number, Supplier, Items, etc.)",
@@ -290,13 +288,16 @@ if st.button("Extract") and inv_file:
290
 
291
  extracted_info = extracted_info or st.session_state.get("last_extracted_info", None)
292
 
293
- # -------------------------------
294
- # LANGGRAPH ReAct DECISION AGENT
295
- # -------------------------------
 
 
 
 
 
 
296
 
297
- def po_match_tool(query: str, context: dict):
298
- invoice = context['invoice']
299
- po_df = context['po_df']
300
  inv_hdr = invoice["invoice_header"]
301
  inv_po_number = inv_hdr.get("purchase_order_number") or inv_hdr.get("order_number") or inv_hdr.get("our_order_number")
302
  inv_supplier = inv_hdr.get("supplier_name")
@@ -319,45 +320,44 @@ def po_match_tool(query: str, context: dict):
319
  return f"PO matched: {matched_po.to_dict()}"
320
  return "No matching PO found."
321
 
322
- def build_decision_agent():
323
- openai_api_key = os.getenv("OPENAI_API_KEY")
324
- llm = ChatOpenAI(
325
- openai_api_key=openai_api_key,
326
- model="gpt-4-1106-preview",
327
- temperature=0,
328
- streaming=False,
329
- # No 'tools' param, classic ReAct only!
330
- )
331
- tools = [
332
- {
333
- "name": "po_match_tool",
334
- "description": "Looks up a PO for a given invoice context.",
335
- "func": po_match_tool,
336
- }
337
- ]
338
- agent = create_react_agent(llm, tools)
339
- graph_builder = StateGraph(agent)
340
- def finish_decision(state, context):
341
- return END, state
342
- graph_builder.add_node("finish", finish_decision)
343
- graph_builder.set_entry_point(agent)
344
- graph_builder.add_edge(agent, END)
345
- return graph_builder.compile()
346
 
347
  if extracted_info is not None and po_df is not None:
348
  if st.button("Make a decision (AI Agent)"):
349
- with st.spinner("Reasoning and making a decision with LangGraph agent..."):
350
- agent_graph = build_decision_agent()
351
- task = (
352
- "Here is an invoice JSON and a list of active POs in context. "
353
- "Step by step, reason whether the invoice matches an active PO and can be approved. "
354
- "If there is a match, state the matched PO, otherwise explain why not. "
355
- "Give a clear final decision: APPROVED or REJECTED."
356
  )
357
- context = {
358
- "invoice": extracted_info,
359
- "po_df": po_df,
360
- }
361
- out = agent_graph.invoke(task, context=context)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  st.subheader("AI Decision")
363
- st.write(out)
 
7
  import mimetypes
8
  import pandas as pd
9
 
 
10
  from langchain_community.chat_models import ChatOpenAI
11
+ from langchain.agents import initialize_agent, Tool, AgentType
 
12
 
13
+ st.set_page_config(page_title="Accounts Payable AI Agent", layout="wide")
14
 
15
  # -------- LLM Model Setup --------
16
  MODELS = {
 
252
  except Exception:
253
  return r.text
254
 
255
+ # --------- Upload PO CSV ---------
256
  st.sidebar.header("Step 1: Upload Active Purchase Orders (POs)")
257
  po_file = st.sidebar.file_uploader(
258
  "Upload POs CSV (must include PO number, Supplier, Items, etc.)",
 
288
 
289
  extracted_info = extracted_info or st.session_state.get("last_extracted_info", None)
290
 
291
+ # --------- Classic ReAct AGENT ---------
292
+ def po_match_tool_func(input_text):
293
+ # This tool receives a string "query" (not structured context!) so it must access globals or session
294
+ # We'll use the extracted_info and po_df from session
295
+ invoice = st.session_state.get("last_extracted_info")
296
+ po_df = st.session_state.get("po_df")
297
+
298
+ if invoice is None or po_df is None:
299
+ return "Invoice or PO data not found."
300
 
 
 
 
301
  inv_hdr = invoice["invoice_header"]
302
  inv_po_number = inv_hdr.get("purchase_order_number") or inv_hdr.get("order_number") or inv_hdr.get("our_order_number")
303
  inv_supplier = inv_hdr.get("supplier_name")
 
320
  return f"PO matched: {matched_po.to_dict()}"
321
  return "No matching PO found."
322
 
323
+ # Save PO df to session for tool access
324
+ if po_df is not None:
325
+ st.session_state["po_df"] = po_df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
 
327
  if extracted_info is not None and po_df is not None:
328
  if st.button("Make a decision (AI Agent)"):
329
+ # Define the tool for the agent (takes input string, outputs string)
330
+ tools = [
331
+ Tool(
332
+ name="po_match_tool",
333
+ func=po_match_tool_func,
334
+ description="Use this tool to check if the invoice matches any PO in the current PO list.",
 
335
  )
336
+ ]
337
+ # Use session state for the LLM agent
338
+ openai_api_key = os.getenv("OPENAI_API_KEY")
339
+ llm = ChatOpenAI(
340
+ openai_api_key=openai_api_key,
341
+ model="gpt-4-1106-preview",
342
+ temperature=0,
343
+ streaming=False,
344
+ )
345
+ agent = initialize_agent(
346
+ tools,
347
+ llm,
348
+ agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
349
+ verbose=True,
350
+ )
351
+ # Build the prompt
352
+ prompt = (
353
+ f"Below is an extracted invoice in JSON and a list of active POs is loaded in the system. "
354
+ f"Use po_match_tool to check if the invoice matches an active PO. "
355
+ f"Step by step, reason whether the invoice matches an active PO and can be approved. "
356
+ f"If there is a match, state the matched PO, otherwise explain why not. "
357
+ f"Give a clear final decision: APPROVED or REJECTED.\n"
358
+ f"Invoice JSON:\n{json.dumps(extracted_info, indent=2)}"
359
+ )
360
+ with st.spinner("AI is reasoning and making a decision..."):
361
+ result = agent.run(prompt)
362
  st.subheader("AI Decision")
363
+ st.write(result)