igortech commited on
Commit
0ae3018
·
verified ·
1 Parent(s): 3e79950

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -106
app.py CHANGED
@@ -1,135 +1,104 @@
1
- import os
2
  import json
 
3
  import difflib
4
- import streamlit as st
5
 
6
- # ===============================
7
- # Load quotes
8
- # ===============================
9
  DATA_PATH = "quotes.json"
10
 
 
11
  def load_quotes():
12
  if os.path.exists(DATA_PATH):
13
- try:
14
- with open(DATA_PATH, "r", encoding="utf-8") as f:
15
- data = json.load(f)
16
- categories = data.get("categories", {})
17
- return categories
18
- except Exception as e:
19
- st.error(f"Error loading data: {e}")
20
- return {}
21
- else:
22
- st.error("quotes.json not found")
23
- return {}
24
 
25
  QUOTES = load_quotes()
26
 
27
- # ===============================
28
- # Fuzzy Matching
29
- # ===============================
30
- def find_best_match(user_input, category_quotes):
31
- all_quotes = []
32
- for sentiment, quotes in category_quotes.items():
33
- for quote in quotes:
34
- all_quotes.append((quote, sentiment))
35
-
36
- if not all_quotes:
37
- return None, None
38
-
39
- # Match user input against quotes
40
- quotes_only = [q[0] for q in all_quotes]
41
- match = difflib.get_close_matches(user_input, quotes_only, n=1, cutoff=0.3)
42
-
43
- if match:
44
- for q, s in all_quotes:
45
- if q == match[0]:
46
- return q, s
47
-
48
- return None, None
49
-
50
- # ===============================
51
- # Response Formatter
52
- # ===============================
53
- def generate_response(user_input, category, sentiment, domain):
54
  if category not in QUOTES:
55
- return "Summary not available.", "No data in this category.", "No related articles."
56
-
57
- category_quotes = QUOTES[category]
58
 
59
- # Handle auto sentiment
 
60
  if sentiment == "auto":
61
- all_quotes = []
62
- for quotes in category_quotes.values():
63
- all_quotes.extend(quotes)
64
- if not all_quotes:
65
- return "Summary not available.", "No quotes available.", "No related articles."
66
  else:
67
- all_quotes = category_quotes.get(sentiment, [])
68
- if not all_quotes:
69
- return "Summary not available.", f"No {sentiment} quotes found.", "No related articles."
70
 
71
- # Best match
72
- best_quote, best_sentiment = find_best_match(user_input, category_quotes)
73
 
74
- # 3-tier response
75
- summary_response = f"The topic seems to be about **{category.lower()}**."
76
- if best_quote:
77
- details_response = best_quote
78
- else:
79
- details_response = "No exact matching quotes found, but here’s what people say in general."
80
-
81
- # Fusion = simple join of first two available quotes
82
- fusion_response = ""
83
- if len(all_quotes) >= 2:
84
- fusion_response = all_quotes[0] + " " + all_quotes[1]
85
- elif all_quotes:
86
- fusion_response = all_quotes[0]
87
- else:
88
- fusion_response = "No quotes available for fusion."
89
 
90
- # Related article (placeholder link with domain search)
91
- if domain.strip():
92
- related_link = f"[Search related articles on {domain}](https://www.google.com/search?q=site:{domain}+{category})"
93
  else:
94
- related_link = f"[Search related articles online](https://www.google.com/search?q={category})"
95
 
96
- return summary_response, details_response, fusion_response, related_link
 
 
 
 
97
 
98
- # ===============================
99
- # Streamlit UI
100
- # ===============================
101
- st.set_page_config(page_title="Campus Life Quotes", layout="centered")
 
102
 
103
- st.title("🎓 Campus Life Quotes Explorer")
104
 
105
- # Align dropdowns side by side
106
- categories = sorted(list(QUOTES.keys()))
107
- col1, col2 = st.columns(2)
108
- with col1:
109
- category = st.selectbox("Category", categories)
110
- with col2:
111
- sentiment = st.selectbox("Sentiment", ["auto", "positive", "negative"])
112
 
113
- user_input = st.text_input("Ask a question:", "")
 
 
114
 
115
- # New: input domain for related articles
116
- domain = st.text_input("Enter a domain for related articles (optional)", "")
117
 
118
- if st.button("Get Response"):
119
- if user_input.strip() == "":
120
- st.warning("Please enter a question.")
121
- else:
122
- summary, details, fusion, related = generate_response(user_input, category, sentiment, domain)
123
 
124
- # New formatted outputs
125
- st.markdown("**Summary:**")
126
- st.write(summary)
127
 
128
- st.markdown("**What real people say:**")
129
- st.write(details)
 
 
 
130
 
131
- st.markdown("**Fusion:**")
132
- st.write(fusion)
133
 
134
- st.markdown("**Related Articles:**")
135
- st.markdown(related)
 
 
1
  import json
2
+ import os
3
  import difflib
4
+ import gradio as gr
5
 
6
+ # Path to your JSON data
 
 
7
  DATA_PATH = "quotes.json"
8
 
9
+ # Load quotes
10
  def load_quotes():
11
  if os.path.exists(DATA_PATH):
12
+ with open(DATA_PATH, "r", encoding="utf-8") as f:
13
+ return json.load(f)
14
+ return {}
 
 
 
 
 
 
 
 
15
 
16
  QUOTES = load_quotes()
17
 
18
+ # Fuzzy match logic (improved with tokenization)
19
+ def fuzzy_match(query, choices):
20
+ tokens = query.lower().split()
21
+ best_score = 0
22
+ best_match = None
23
+ for choice in choices:
24
+ score = difflib.SequenceMatcher(None, query.lower(), choice.lower()).ratio()
25
+ token_overlap = len(set(tokens) & set(choice.lower().split())) / max(len(tokens), 1)
26
+ combined_score = (score + token_overlap) / 2
27
+ if combined_score > best_score:
28
+ best_score = combined_score
29
+ best_match = choice
30
+ return best_match, best_score
31
+
32
+ # Handle user query
33
+ def handle_query(user_message, category, sentiment, url_restrict):
34
+ responses = []
35
+
36
+ # Validate category
 
 
 
 
 
 
 
 
37
  if category not in QUOTES:
38
+ return [{"role": "assistant", "content": "Category not found in dataset."}]
 
 
39
 
40
+ # Collect relevant quotes
41
+ choices = []
42
  if sentiment == "auto":
43
+ for sent in QUOTES[category]:
44
+ choices.extend(QUOTES[category][sent])
 
 
 
45
  else:
46
+ choices = QUOTES[category].get(sentiment, [])
 
 
47
 
48
+ if not choices:
49
+ return [{"role": "assistant", "content": "No quotes available for this category/sentiment."}]
50
 
51
+ # Fuzzy match query against quotes
52
+ best_match, score = fuzzy_match(user_message, choices)
53
+
54
+ # === 3-tier response ===
55
+ # Tier 1: Summary (simple echo of category/topic)
56
+ summary = f"**Topic Summary:** This question seems related to *{category.replace('_', ' ')}*."
 
 
 
 
 
 
 
 
 
57
 
58
+ # Tier 2: "What real people say"
59
+ if best_match and score > 0.3:
60
+ details = f"**What real people say:**\n{best_match}"
61
  else:
62
+ details = "**What real people say:**\nSorry, no close match found."
63
 
64
+ # Tier 3: External article reference (stub)
65
+ if url_restrict.strip():
66
+ external = f"**Similar articles (restricted to {url_restrict}):**\n[Search results on {url_restrict}](https://www.google.com/search?q={user_message}+site:{url_restrict})"
67
+ else:
68
+ external = "**Similar articles:**\n[Search on Google](https://www.google.com/search?q=" + user_message.replace(" ", "+") + ")"
69
 
70
+ responses.extend([
71
+ {"role": "assistant", "content": summary},
72
+ {"role": "assistant", "content": details},
73
+ {"role": "assistant", "content": external}
74
+ ])
75
 
76
+ return responses
77
 
78
+ # Build Gradio UI
79
+ with gr.Blocks() as demo:
80
+ gr.Markdown("## 🎓 College Life Q&A Chatbot")
 
 
 
 
81
 
82
+ with gr.Row():
83
+ category = gr.Dropdown(choices=list(QUOTES.keys()), label="Category", interactive=True)
84
+ sentiment = gr.Dropdown(choices=["auto", "positive", "negative"], value="auto", label="Sentiment", interactive=True)
85
 
86
+ url_restrict = gr.Textbox(label="Restrict search to domain (optional)", placeholder="e.g., nytimes.com")
 
87
 
88
+ chatbot = gr.Chatbot(label="Conversation", type="messages", height=400)
89
+ msg = gr.Textbox(label="Ask a question")
 
 
 
90
 
91
+ with gr.Row():
92
+ clear_btn = gr.Button("Clear Chat")
 
93
 
94
+ def respond(message, chat_history, category, sentiment, url_restrict):
95
+ bot_msgs = handle_query(message, category, sentiment, url_restrict)
96
+ chat_history.append({"role": "user", "content": message})
97
+ chat_history.extend(bot_msgs)
98
+ return "", chat_history
99
 
100
+ msg.submit(respond, [msg, chatbot, category, sentiment, url_restrict], [msg, chatbot])
101
+ clear_btn.click(lambda: [], None, chatbot)
102
 
103
+ if __name__ == "__main__":
104
+ demo.launch()