igortech commited on
Commit
c03a84c
·
verified ·
1 Parent(s): 6de5c00

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -101
app.py CHANGED
@@ -1,136 +1,117 @@
1
  import json
 
2
  import os
3
  import datetime
4
- import random
5
- import difflib
6
  import gradio as gr
7
- import csv
8
 
9
  # -----------------------------
10
- # Config / Data Loading
11
  # -----------------------------
12
  DATA_PATH = "quotes.json"
13
 
14
  def load_quotes():
15
  if os.path.exists(DATA_PATH):
16
- try:
17
- with open(DATA_PATH, "r", encoding="utf-8") as f:
18
- data = json.load(f)
19
- if isinstance(data, dict):
20
- print(f"Loaded dataset from {DATA_PATH} with {len(data)} categories.")
21
- return data
22
- except Exception as e:
23
- print(f"Failed to load {DATA_PATH}: {e}")
24
- print("No dataset found. Upload one via the UI.")
25
  return {}
26
 
27
  QUOTES = load_quotes()
28
- STAGED_RESPONSES = []
29
 
30
  # -----------------------------
31
- # Utility Functions
32
  # -----------------------------
33
- def best_match_quote(category, user_text):
34
- if category not in QUOTES or not QUOTES[category]:
35
- return "No quotes available for this category."
36
 
 
 
 
 
37
  pool = QUOTES[category]
38
- q_tokens = set(user_text.lower().split())
39
- best_quote = None
 
 
40
  best_score = -1
 
 
41
  for entry in pool:
42
- quote = entry.get("quote", "")
43
- qtoks = set(quote.lower().split())
44
- score = len(q_tokens & qtoks)
45
  if score > best_score:
46
  best_score = score
47
- best_quote = quote
48
 
49
- if best_score == 0:
50
- best_quote = random.choice(pool).get("quote", "")
51
- return best_quote
52
 
53
- def generate_3fold_response(category, user_text):
54
- # 1. Summary sentence (first line of best matching quote)
55
- best_quote = best_match_quote(category, user_text)
56
- summary = best_quote.split('.')[0] + '.'
57
 
58
- # 2. Fusion of quotes in category
59
- fused = " ".join([q.get("quote", "") for q in QUOTES.get(category, [])][:3])
 
 
60
 
61
- # 3. Placeholder link (can be replaced with site search later)
62
- link = f"https://www.google.com/search?q={category}+college+site:example.com"
 
63
 
64
- return [
65
- f"Summary: \n{summary}",
66
- f"What real people say: \n{fused}",
67
- f"Related link: \n{link}"
68
- ]
 
69
 
70
  # -----------------------------
71
- # Gradio Callbacks
72
  # -----------------------------
73
- def respond(message, history, category, sentiment):
74
  if not message.strip():
75
  return "", history
76
- responses = generate_3fold_response(category, message)
77
- history.append((message, responses))
 
 
 
 
 
 
 
78
  return "", history
79
 
80
  def clear_chat():
81
  return None
82
 
83
- def stage_response(chat_history, category):
84
- if not chat_history:
85
- return gr.update(value="No conversation to stage.")
86
- last_user, last_bot = chat_history[-1]
87
- if category not in QUOTES:
88
- QUOTES[category] = []
89
- QUOTES[category].append({"quote": last_bot[1].replace("What real people say: \n","")})
90
- STAGED_RESPONSES.append((last_user, last_bot))
91
- return gr.update(value=f"Last message staged to category '{category}'.")
92
-
93
- def download_csv():
94
- if not STAGED_RESPONSES:
95
- return None
96
- filename = "staged_conversation.csv"
97
- with open(filename, "w", newline="", encoding="utf-8") as csvfile:
98
- writer = csv.writer(csvfile)
99
- writer.writerow(["User", "Summary", "What people say", "Link"])
100
- for user_msg, bot_resp in STAGED_RESPONSES:
101
- writer.writerow([user_msg] + bot_resp)
102
- return filename
103
-
104
- def upload_json(filepath):
105
- global QUOTES
106
- try:
107
- with open(filepath, "r", encoding="utf-8") as f:
108
- data = json.load(f)
109
- if not isinstance(data, dict):
110
- return gr.update(value="Upload failed: JSON root must be an object."), gr.update(choices=[])
111
- QUOTES = data
112
- cats = sorted(list(QUOTES.keys()))
113
- return f"Loaded {len(cats)} categories from {filepath}.", gr.update(choices=cats, value=cats[0] if cats else None)
114
- except Exception as e:
115
- return f"Error loading file: {e}", gr.update(choices=[])
116
-
117
- def download_dataset():
118
- tmp = "quotes_export.json"
119
- with open(tmp, "w", encoding="utf-8") as f:
120
- json.dump(QUOTES, f, indent=2, ensure_ascii=False)
121
  return tmp
122
 
123
  # -----------------------------
124
- # Gradio UI
125
  # -----------------------------
126
  with gr.Blocks() as demo:
127
- gr.Markdown("## 🎓 College Life Chatbot — 3-Fold Response + Staged Export")
128
 
129
  initial_categories = sorted(list(QUOTES.keys()))
130
 
131
  with gr.Row():
132
- category = gr.Dropdown(label="Category", choices=initial_categories, value=(initial_categories[0] if initial_categories else None))
133
- sentiment = gr.Dropdown(label="Sentiment", choices=["auto", "positive", "negative"], value="auto")
 
 
 
134
 
135
  chatbot = gr.Chatbot(label="Conversation", height=360, type="messages")
136
  msg = gr.Textbox(label="Your message", placeholder="Ask something like: 'Is food good in college?'", autofocus=True)
@@ -138,24 +119,13 @@ with gr.Blocks() as demo:
138
  clear = gr.Button("Clear")
139
 
140
  with gr.Row():
141
- stage_btn = gr.Button("Stage conversation to category")
142
- staged_status = gr.Textbox(label="Staging status", interactive=False)
143
-
144
- with gr.Row():
145
- uploader = gr.File(label="Upload dataset (.json)", file_types=[".json"], type="filepath")
146
- upload_status = gr.Textbox(label="Upload status", interactive=False)
147
- downloader = gr.File(label="Download current dataset")
148
- download_csv_btn = gr.File(label="Download staged conversation CSV")
149
 
150
  # Wire events
151
- msg.submit(respond, [msg, chatbot, category, sentiment], [msg, chatbot])
152
- send.click(respond, [msg, chatbot, category, sentiment], [msg, chatbot])
153
  clear.click(clear_chat, None, chatbot, queue=False)
154
-
155
- stage_btn.click(stage_response, [chatbot, category], staged_status)
156
- uploader.upload(upload_json, uploader, [upload_status, category])
157
- downloader.download(download_dataset)
158
- download_csv_btn.download(download_csv)
159
 
160
  # -----------------------------
161
  # Startup log
 
1
  import json
2
+ import random
3
  import os
4
  import datetime
 
 
5
  import gradio as gr
 
6
 
7
  # -----------------------------
8
+ # Config / data loading
9
  # -----------------------------
10
  DATA_PATH = "quotes.json"
11
 
12
  def load_quotes():
13
  if os.path.exists(DATA_PATH):
14
+ with open(DATA_PATH, "r", encoding="utf-8") as f:
15
+ data = json.load(f)
16
+ print(f"Loaded dataset from {DATA_PATH} with {len(data)} categories.")
17
+ return data
18
+ print("No dataset found. Please upload a JSON file via the UI.")
 
 
 
 
19
  return {}
20
 
21
  QUOTES = load_quotes()
 
22
 
23
  # -----------------------------
24
+ # Helper functions
25
  # -----------------------------
26
+ def tokenize(text):
27
+ return set(text.lower().split())
 
28
 
29
+ def best_match_quote(category, user_text):
30
+ """Find the quote with the most token overlap."""
31
+ if category not in QUOTES:
32
+ return None
33
  pool = QUOTES[category]
34
+ if not pool:
35
+ return None
36
+
37
+ q_tokens = tokenize(user_text)
38
  best_score = -1
39
+ best_quote = None
40
+
41
  for entry in pool:
42
+ quote_tokens = tokenize(entry["quote"])
43
+ score = len(q_tokens & quote_tokens)
 
44
  if score > best_score:
45
  best_score = score
46
+ best_quote = entry["quote"]
47
 
48
+ # fallback
49
+ if not best_quote:
50
+ best_quote = random.choice(pool)["quote"]
51
 
52
+ return best_quote
 
 
 
53
 
54
+ def generate_response(category, user_text):
55
+ """Produce 3-fold response based on category quotes."""
56
+ if category not in QUOTES:
57
+ return ["No quotes found for this category.", "", ""]
58
 
59
+ pool = QUOTES[category]
60
+ if not pool:
61
+ return ["No quotes available.", "", ""]
62
 
63
+ # For simplicity, pick up to 2-3 quotes for summary
64
+ sampled = random.sample(pool, min(2, len(pool)))
65
+ summary = " ".join([s["quote"].split(".")[0] + "." for s in sampled]) # first sentence
66
+ details = " ".join([s["quote"] for s in sampled])
67
+ suggested_url = "https://www.example.com/search?q=" + category.replace(" ", "+")
68
+ return [summary, details, suggested_url]
69
 
70
  # -----------------------------
71
+ # Gradio callbacks
72
  # -----------------------------
73
+ def respond(message, history, category):
74
  if not message.strip():
75
  return "", history
76
+
77
+ summary, details, suggested_url = generate_response(category, message)
78
+
79
+ # Append messages in Gradio "messages" format
80
+ history.append({"role": "user", "content": message})
81
+ history.append({"role": "assistant", "content": f"Summary:\n{summary}"})
82
+ history.append({"role": "assistant", "content": f"What real people say:\n{details}"})
83
+ history.append({"role": "assistant", "content": f"Suggested URL:\n{suggested_url}"})
84
+
85
  return "", history
86
 
87
  def clear_chat():
88
  return None
89
 
90
+ def download_current_csv(history):
91
+ """Export current conversation to CSV."""
92
+ import csv
93
+ tmp = "conversation_export.csv"
94
+ with open(tmp, "w", newline="", encoding="utf-8") as f:
95
+ writer = csv.writer(f)
96
+ writer.writerow(["role", "content"])
97
+ for msg in history:
98
+ writer.writerow([msg["role"], msg["content"]])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  return tmp
100
 
101
  # -----------------------------
102
+ # UI
103
  # -----------------------------
104
  with gr.Blocks() as demo:
105
+ gr.Markdown("## 🎓 College Life Chatbot — 3-Fold Responses")
106
 
107
  initial_categories = sorted(list(QUOTES.keys()))
108
 
109
  with gr.Row():
110
+ category = gr.Dropdown(
111
+ label="Category",
112
+ choices=initial_categories,
113
+ value=(initial_categories[0] if initial_categories else None)
114
+ )
115
 
116
  chatbot = gr.Chatbot(label="Conversation", height=360, type="messages")
117
  msg = gr.Textbox(label="Your message", placeholder="Ask something like: 'Is food good in college?'", autofocus=True)
 
119
  clear = gr.Button("Clear")
120
 
121
  with gr.Row():
122
+ download_csv = gr.File(label="Export conversation to CSV")
 
 
 
 
 
 
 
123
 
124
  # Wire events
125
+ msg.submit(respond, [msg, chatbot, category], [msg, chatbot])
126
+ send.click(respond, [msg, chatbot, category], [msg, chatbot])
127
  clear.click(clear_chat, None, chatbot, queue=False)
128
+ download_csv.download(lambda h: download_current_csv(h), chatbot, download_csv)
 
 
 
 
129
 
130
  # -----------------------------
131
  # Startup log