Seth0330 commited on
Commit
0fa3514
·
verified ·
1 Parent(s): c7cc5ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -46
app.py CHANGED
@@ -1,50 +1,12 @@
1
  import streamlit as st
2
  import json
3
 
4
- # --- Constants for searching ---
5
- COMMON_NAME_KEYS = ["user", "username", "name", "fullName", "firstName", "lastName"]
6
  LOGIN_KEYS = ["lastLogin", "login", "loggedIn", "lastLoggedIn", "last_login", "last_logged_in"]
7
 
8
- # --- Session state setup ---
9
- if "json_data" not in st.session_state:
10
- st.session_state.json_data = {}
11
- if "messages" not in st.session_state:
12
- st.session_state.messages = []
13
- if "temp_input" not in st.session_state:
14
- st.session_state.temp_input = ""
15
- if "files_loaded" not in st.session_state:
16
- st.session_state.files_loaded = False
17
-
18
- st.set_page_config(page_title="Instant JSON Q&A", layout="wide")
19
- st.title("Instant JSON-Backed AI Q&A (No More Clarifying Loops)")
20
-
21
- # --- Upload area ---
22
- st.sidebar.header("Upload Multiple JSON Files")
23
- uploaded_files = st.sidebar.file_uploader(
24
- "Choose one or more JSON files", type="json", accept_multiple_files=True
25
- )
26
-
27
- if uploaded_files and not st.session_state.files_loaded:
28
- st.session_state.json_data.clear()
29
- for f in uploaded_files:
30
- try:
31
- content = json.load(f)
32
- st.session_state.json_data[f.name] = content
33
- st.sidebar.success(f"Loaded: {f.name}")
34
- except Exception as e:
35
- st.sidebar.error(f"Error reading {f.name}: {e}")
36
- st.session_state.messages = []
37
- st.session_state.files_loaded = True
38
- elif not uploaded_files:
39
- st.session_state.json_data.clear()
40
- st.session_state.files_loaded = False
41
-
42
- # --- Robust normalization function for matching ---
43
  def normalize(s):
44
- # Lowercase, remove underscores/dashes, strip, collapse double spaces
45
  return str(s).lower().replace("_", " ").replace("-", " ").replace(".", " ").strip()
46
 
47
- # --- Recursive user search with robust matching ---
48
  def recursive_find_user(target_name):
49
  matches = []
50
  norm_target = normalize(target_name)
@@ -52,7 +14,8 @@ def recursive_find_user(target_name):
52
  def _search(obj, path):
53
  if isinstance(obj, dict):
54
  for k, v in obj.items():
55
- if k in COMMON_NAME_KEYS and norm_target in normalize(v):
 
56
  login_info = {}
57
  for lk in LOGIN_KEYS:
58
  if lk in obj:
@@ -64,6 +27,21 @@ def recursive_find_user(target_name):
64
  "file": file_name,
65
  "login_info": login_info
66
  })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  _search(v, path + [k])
68
  elif isinstance(obj, list):
69
  for idx, item in enumerate(obj):
@@ -71,7 +49,6 @@ def recursive_find_user(target_name):
71
  _search(data, [])
72
  return matches
73
 
74
- # --- Show all user keys/values (for debug) ---
75
  def show_all_users():
76
  found = []
77
  for file_name, data in st.session_state.json_data.items():
@@ -79,7 +56,12 @@ def show_all_users():
79
  if isinstance(obj, dict):
80
  for k, v in obj.items():
81
  if k in COMMON_NAME_KEYS:
82
- found.append(f"{file_name} | {'.'.join(path + [k])} = {v}")
 
 
 
 
 
83
  recursive(v, path + [k])
84
  elif isinstance(obj, list):
85
  for idx, item in enumerate(obj):
@@ -87,10 +69,8 @@ def show_all_users():
87
  recursive(data, [])
88
  return found
89
 
90
- # --- Main Q&A logic ---
91
  import re
92
  def handle_user_query(query):
93
- # Try to extract a likely user name from the query
94
  patterns = [
95
  r"(?:last\s*login.*?for|when\s+did)\s+([a-zA-Z0-9 _\-\.]+)",
96
  r"when\s+was\s+([a-zA-Z0-9 _\-\.]+)\s+last\s+(?:login|logged\s*in)",
@@ -104,7 +84,6 @@ def handle_user_query(query):
104
  found_name = m.group(1).strip()
105
  break
106
  if not found_name:
107
- # Fallback: look for first capitalized word or phrase
108
  m = re.search(r"([A-Z][a-z]+(?: [A-Z][a-z]+)*)", query)
109
  if m:
110
  found_name = m.group(1).strip()
@@ -122,7 +101,37 @@ def handle_user_query(query):
122
  else:
123
  return "Sorry, I can only answer direct user info queries (e.g., 'When did Bob the Builder last login?')."
124
 
125
- # --- Chat UI ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  st.markdown("### Ask about any user directly (e.g. 'When did Bob the Builder last login?')")
127
  for msg in st.session_state.messages:
128
  if msg["role"] == "user":
 
1
  import streamlit as st
2
  import json
3
 
4
+ COMMON_NAME_KEYS = ["user", "username", "name", "fullName", "firstName", "lastName", "customer"]
 
5
  LOGIN_KEYS = ["lastLogin", "login", "loggedIn", "lastLoggedIn", "last_login", "last_logged_in"]
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  def normalize(s):
 
8
  return str(s).lower().replace("_", " ").replace("-", " ").replace(".", " ").strip()
9
 
 
10
  def recursive_find_user(target_name):
11
  matches = []
12
  norm_target = normalize(target_name)
 
14
  def _search(obj, path):
15
  if isinstance(obj, dict):
16
  for k, v in obj.items():
17
+ # Direct match for string value
18
+ if k in COMMON_NAME_KEYS and isinstance(v, str) and norm_target in normalize(v):
19
  login_info = {}
20
  for lk in LOGIN_KEYS:
21
  if lk in obj:
 
27
  "file": file_name,
28
  "login_info": login_info
29
  })
30
+ # Nested dict, e.g., user: { username: ... }
31
+ if k in COMMON_NAME_KEYS and isinstance(v, dict):
32
+ for nk, nv in v.items():
33
+ if nk in COMMON_NAME_KEYS and norm_target in normalize(nv):
34
+ login_info = {}
35
+ for lk in LOGIN_KEYS:
36
+ if lk in obj:
37
+ login_info[lk] = obj[lk]
38
+ matches.append({
39
+ "match_path": path + [k, nk],
40
+ "matched_name": nv,
41
+ "record": obj,
42
+ "file": file_name,
43
+ "login_info": login_info
44
+ })
45
  _search(v, path + [k])
46
  elif isinstance(obj, list):
47
  for idx, item in enumerate(obj):
 
49
  _search(data, [])
50
  return matches
51
 
 
52
  def show_all_users():
53
  found = []
54
  for file_name, data in st.session_state.json_data.items():
 
56
  if isinstance(obj, dict):
57
  for k, v in obj.items():
58
  if k in COMMON_NAME_KEYS:
59
+ if isinstance(v, str):
60
+ found.append(f"{file_name} | {'.'.join(path + [k])} = {v}")
61
+ elif isinstance(v, dict):
62
+ for nk, nv in v.items():
63
+ if nk in COMMON_NAME_KEYS:
64
+ found.append(f"{file_name} | {'.'.join(path + [k, nk])} = {nv}")
65
  recursive(v, path + [k])
66
  elif isinstance(obj, list):
67
  for idx, item in enumerate(obj):
 
69
  recursive(data, [])
70
  return found
71
 
 
72
  import re
73
  def handle_user_query(query):
 
74
  patterns = [
75
  r"(?:last\s*login.*?for|when\s+did)\s+([a-zA-Z0-9 _\-\.]+)",
76
  r"when\s+was\s+([a-zA-Z0-9 _\-\.]+)\s+last\s+(?:login|logged\s*in)",
 
84
  found_name = m.group(1).strip()
85
  break
86
  if not found_name:
 
87
  m = re.search(r"([A-Z][a-z]+(?: [A-Z][a-z]+)*)", query)
88
  if m:
89
  found_name = m.group(1).strip()
 
101
  else:
102
  return "Sorry, I can only answer direct user info queries (e.g., 'When did Bob the Builder last login?')."
103
 
104
+ # --- Streamlit UI ---
105
+ if "json_data" not in st.session_state:
106
+ st.session_state.json_data = {}
107
+ if "messages" not in st.session_state:
108
+ st.session_state.messages = []
109
+ if "temp_input" not in st.session_state:
110
+ st.session_state.temp_input = ""
111
+ if "files_loaded" not in st.session_state:
112
+ st.session_state.files_loaded = False
113
+
114
+ st.set_page_config(page_title="Instant JSON Q&A", layout="wide")
115
+ st.title("Instant JSON-Backed AI Q&A (Now Handles Nested Users!)")
116
+
117
+ uploaded_files = st.sidebar.file_uploader(
118
+ "Choose one or more JSON files", type="json", accept_multiple_files=True
119
+ )
120
+ if uploaded_files and not st.session_state.files_loaded:
121
+ st.session_state.json_data.clear()
122
+ for f in uploaded_files:
123
+ try:
124
+ content = json.load(f)
125
+ st.session_state.json_data[f.name] = content
126
+ st.sidebar.success(f"Loaded: {f.name}")
127
+ except Exception as e:
128
+ st.sidebar.error(f"Error reading {f.name}: {e}")
129
+ st.session_state.messages = []
130
+ st.session_state.files_loaded = True
131
+ elif not uploaded_files:
132
+ st.session_state.json_data.clear()
133
+ st.session_state.files_loaded = False
134
+
135
  st.markdown("### Ask about any user directly (e.g. 'When did Bob the Builder last login?')")
136
  for msg in st.session_state.messages:
137
  if msg["role"] == "user":