rairo commited on
Commit
079d74e
Β·
verified Β·
1 Parent(s): f20da2b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -56
app.py CHANGED
@@ -7,6 +7,7 @@ import nest_asyncio
7
  import os
8
  import subprocess
9
  import io
 
10
  from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings
11
  from langchain.vectorstores import FAISS
12
  from langchain.text_splitter import CharacterTextSplitter
@@ -30,17 +31,60 @@ graph_config = {
30
  }
31
 
32
  def get_data(search_term):
33
- # Combine the user input with 'grants'
34
- full_prompt = f"search for {search_term} grants\n\nList me all grants or funds with:\n- Grant name/title\n- Short summary (50-100 characters)\n- Funding organization\n- Grant value (numeric only)\n- Application deadline\n- Eligible countries\n- Sector/field\n- Eligibility criteria\nReturn in JSON format."
35
- search_graph = SearchGraph(
36
- prompt=full_prompt,
37
- config=graph_config,
 
 
 
 
 
 
 
 
 
 
 
 
38
  )
39
- return search_graph.run()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
  def process_multiple_search_terms(search_terms):
42
  """
43
- Process multiple search terms with enhanced progress tracking and user feedback.
 
44
  """
45
  all_data = {"grants": []}
46
  progress_bar = st.progress(0)
@@ -48,33 +92,29 @@ def process_multiple_search_terms(search_terms):
48
  total_terms = len(search_terms)
49
 
50
  for index, term in enumerate(search_terms):
51
- try:
52
- term = term.strip()
53
- if not term:
54
- continue
55
-
56
- progress = (index + 1) / total_terms
57
- progress_bar.progress(progress)
58
- status_container.markdown(
59
- f"""
60
- **Processing Grant Opportunities** πŸš€
61
- Searching term {index+1} of {total_terms}: `{term}`
62
  <br>
63
  <p style='font-size: 0.9em; color: #6699CC;'>Completed: {index}/{total_terms} | Remaining: {total_terms - index - 1}</p>
64
  """,
65
- unsafe_allow_html=True,
66
- )
67
-
68
- result = get_data(term)
69
- # Expecting a JSON with a "grants" key
70
- if result and "grants" in result:
71
- all_data["grants"].extend(result["grants"])
72
- except Exception as e:
73
- st.error(f"⚠️ Error processing search term: {term} - {str(e)}")
74
- continue
75
 
 
 
 
76
  progress_bar.empty()
77
  status_container.empty()
 
 
78
  return all_data
79
 
80
  def convert_to_csv(data):
@@ -106,11 +146,9 @@ Here is the extracted grant data in JSON format:
106
  User's question: {query}
107
  Answer the question based on the provided grant data.
108
  """
109
-
110
  llm = ChatGoogleGenerativeAI(
111
  model="gemini-2.0-flash-thinking-exp", google_api_key=GOOGLE_API_KEY, temperature=0
112
  )
113
-
114
  response = llm.invoke(prompt)
115
  return response
116
 
@@ -121,7 +159,6 @@ def get_shareable_link(file_data, file_name, file_type):
121
  def main():
122
  st.set_page_config(page_title="Quantilytix Grant Finder", page_icon="πŸ’°", layout="wide")
123
  st.title("πŸ’° Quantilytix Grant Finder")
124
-
125
  st.markdown("""
126
  <div style="text-align: justify;">
127
  <p>
@@ -141,7 +178,7 @@ def main():
141
  if "chat_interface_active" not in st.session_state:
142
  st.session_state.chat_interface_active = False
143
 
144
- # Search Term Input in Sidebar
145
  search_input = st.sidebar.text_area(
146
  "Enter Search Terms (one per line)",
147
  height=150,
@@ -153,23 +190,20 @@ def main():
153
  if search_input:
154
  search_terms = [term.strip() for term in search_input.split("\n") if term.strip()]
155
  if search_terms:
156
- try:
157
- with st.spinner("Searching in progress... Please wait patiently."):
158
- result = process_multiple_search_terms(search_terms)
159
- st.session_state.scraped_data = result
160
  st.sidebar.success(f"βœ… Found {len(result['grants'])} grant opportunities from {len(search_terms)} search terms!")
161
- except Exception as e:
162
- st.sidebar.error(f"🚨 Searching process encountered an error: {e}")
163
  else:
164
  st.sidebar.warning("⚠️ Please enter valid search terms.")
165
  else:
166
  st.sidebar.warning("⚠️ Please enter at least one search term to begin.")
167
 
168
- # Sidebar: Download and Share Options
169
  if st.session_state.scraped_data and st.session_state.scraped_data.get('grants'):
170
  st.sidebar.markdown("---")
171
  st.sidebar.subheader("Download & Share")
172
-
173
  selected_format = st.sidebar.selectbox("Download As:", ("CSV", "Excel"), key="download_format_selector")
174
  if selected_format == "CSV":
175
  file_data = convert_to_csv(st.session_state.scraped_data)
@@ -179,16 +213,13 @@ def main():
179
  file_data = convert_to_excel(st.session_state.scraped_data)
180
  file_name = "grants_data.xlsx"
181
  file_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
182
-
183
  download_link_html = f"<a href='data:{file_type};base64,{base64.b64encode(file_data).decode()}' download='{file_name}'><button style='background-color:#4CAF50;color:white;padding:10px 15px;border:none;border-radius:4px;'>⬇️ Download {selected_format}</button></a>"
184
  st.sidebar.markdown(download_link_html, unsafe_allow_html=True)
185
-
186
  shareable_link = get_shareable_link(file_data, file_name, file_type)
187
  whatsapp_url = f"https://api.whatsapp.com/send?text={urllib.parse.quote(f'Check out these grant opportunities: {shareable_link}')}"
188
  email_subject = urllib.parse.quote("Grant Opportunities File")
189
  email_body = urllib.parse.quote(f"Download the grant opportunities file here: {shareable_link}")
190
  email_url = f"mailto:?subject={email_subject}&body={email_body}"
191
-
192
  st.sidebar.markdown("<div style='margin-top:10px;'>Share via:</div>", unsafe_allow_html=True)
193
  st.sidebar.markdown(f"πŸ“± [WhatsApp]({whatsapp_url}) | πŸ“§ [Email]({email_url})", unsafe_allow_html=True)
194
 
@@ -200,25 +231,22 @@ def main():
200
  st.session_state.chat_history = []
201
  st.sidebar.success("Knowledge base loaded!")
202
 
203
- # Sidebar: Chat Interface
204
- if st.session_state.get("chat_interface_active"):
205
- st.sidebar.markdown("---")
206
- st.sidebar.subheader("πŸ’¬ Chat with Grants Bot")
207
- query = st.sidebar.text_input("Your question:", key="chat_input")
208
- if query:
209
- with st.spinner("Generating response..."):
210
- response = chat_with_knowledge_base(query)
211
- # Assume response returns a dictionary with key 'answer'
212
- answer = response["answer"] if isinstance(response, dict) and "answer" in response else response
213
- st.session_state.chat_history.append({"query": query, "response": answer})
214
-
215
- # Main area: Preview data and chat history
216
  st.markdown("---")
217
  if st.session_state.scraped_data and st.session_state.scraped_data.get('grants'):
218
  st.header("πŸ“Š Found Grant Data")
219
  with st.expander(f"πŸ“Š Preview Grant Data ({len(st.session_state.scraped_data['grants'])} grants)"):
220
  st.dataframe(st.session_state.scraped_data["grants"])
221
 
 
 
 
 
 
 
 
 
 
222
  if st.session_state.chat_history:
223
  st.subheader("Chat History")
224
  for chat in st.session_state.chat_history:
 
7
  import os
8
  import subprocess
9
  import io
10
+ import time
11
  from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings
12
  from langchain.vectorstores import FAISS
13
  from langchain.text_splitter import CharacterTextSplitter
 
31
  }
32
 
33
  def get_data(search_term):
34
+ """
35
+ Run the SearchGraph for a given search term.
36
+ If a rate-limit error (202) occurs, wait 10 seconds and retry.
37
+ If no results are returned or an error persists, notify the user.
38
+ """
39
+ full_prompt = (
40
+ f"search for {search_term} grants\n\n"
41
+ "List me all grants or funds with:\n"
42
+ "- Grant name/title\n"
43
+ "- Short summary (50-100 characters)\n"
44
+ "- Funding organization\n"
45
+ "- Grant value (numeric only)\n"
46
+ "- Application deadline\n"
47
+ "- Eligible countries\n"
48
+ "- Sector/field\n"
49
+ "- Eligibility criteria\n"
50
+ "Return in JSON format."
51
  )
52
+ try:
53
+ search_graph = SearchGraph(
54
+ prompt=full_prompt,
55
+ config=graph_config,
56
+ )
57
+ result = search_graph.run()
58
+ if not result or not result.get("grants"):
59
+ st.error("No results returned. Please try again with different search terms.")
60
+ return {}
61
+ return result
62
+ except Exception as e:
63
+ err_str = str(e)
64
+ if "202" in err_str:
65
+ st.warning("Rate limit reached (202). Waiting 10 seconds before retrying...")
66
+ time.sleep(10)
67
+ try:
68
+ search_graph = SearchGraph(
69
+ prompt=full_prompt,
70
+ config=graph_config,
71
+ )
72
+ result = search_graph.run()
73
+ if not result or not result.get("grants"):
74
+ st.error("No results returned after retry. Please try again with different search terms.")
75
+ return {}
76
+ return result
77
+ except Exception as e2:
78
+ st.error(f"Retry failed: {e2}. Please try again later.")
79
+ return {}
80
+ else:
81
+ st.error(f"An error occurred: {e}. Please try again.")
82
+ return {}
83
 
84
  def process_multiple_search_terms(search_terms):
85
  """
86
+ Process multiple search terms with progress tracking.
87
+ Returns a dictionary with a 'grants' key containing combined results.
88
  """
89
  all_data = {"grants": []}
90
  progress_bar = st.progress(0)
 
92
  total_terms = len(search_terms)
93
 
94
  for index, term in enumerate(search_terms):
95
+ term = term.strip()
96
+ if not term:
97
+ continue
98
+
99
+ progress = (index + 1) / total_terms
100
+ progress_bar.progress(progress)
101
+ status_container.markdown(
102
+ f"""
103
+ **Processing Grant Opportunities** πŸš€
104
+ Searching term {index+1} of {total_terms}: `{term}`
 
105
  <br>
106
  <p style='font-size: 0.9em; color: #6699CC;'>Completed: {index}/{total_terms} | Remaining: {total_terms - index - 1}</p>
107
  """,
108
+ unsafe_allow_html=True,
109
+ )
 
 
 
 
 
 
 
 
110
 
111
+ result = get_data(term)
112
+ if result and result.get("grants"):
113
+ all_data["grants"].extend(result["grants"])
114
  progress_bar.empty()
115
  status_container.empty()
116
+ if not all_data["grants"]:
117
+ st.error("No grant opportunities were found. Please try again with different search terms.")
118
  return all_data
119
 
120
  def convert_to_csv(data):
 
146
  User's question: {query}
147
  Answer the question based on the provided grant data.
148
  """
 
149
  llm = ChatGoogleGenerativeAI(
150
  model="gemini-2.0-flash-thinking-exp", google_api_key=GOOGLE_API_KEY, temperature=0
151
  )
 
152
  response = llm.invoke(prompt)
153
  return response
154
 
 
159
  def main():
160
  st.set_page_config(page_title="Quantilytix Grant Finder", page_icon="πŸ’°", layout="wide")
161
  st.title("πŸ’° Quantilytix Grant Finder")
 
162
  st.markdown("""
163
  <div style="text-align: justify;">
164
  <p>
 
178
  if "chat_interface_active" not in st.session_state:
179
  st.session_state.chat_interface_active = False
180
 
181
+ # Sidebar: Search Term Input
182
  search_input = st.sidebar.text_area(
183
  "Enter Search Terms (one per line)",
184
  height=150,
 
190
  if search_input:
191
  search_terms = [term.strip() for term in search_input.split("\n") if term.strip()]
192
  if search_terms:
193
+ with st.spinner("Searching in progress... Please wait patiently."):
194
+ result = process_multiple_search_terms(search_terms)
195
+ st.session_state.scraped_data = result
196
+ if result.get("grants"):
197
  st.sidebar.success(f"βœ… Found {len(result['grants'])} grant opportunities from {len(search_terms)} search terms!")
 
 
198
  else:
199
  st.sidebar.warning("⚠️ Please enter valid search terms.")
200
  else:
201
  st.sidebar.warning("⚠️ Please enter at least one search term to begin.")
202
 
203
+ # Sidebar: Download & Share Controls
204
  if st.session_state.scraped_data and st.session_state.scraped_data.get('grants'):
205
  st.sidebar.markdown("---")
206
  st.sidebar.subheader("Download & Share")
 
207
  selected_format = st.sidebar.selectbox("Download As:", ("CSV", "Excel"), key="download_format_selector")
208
  if selected_format == "CSV":
209
  file_data = convert_to_csv(st.session_state.scraped_data)
 
213
  file_data = convert_to_excel(st.session_state.scraped_data)
214
  file_name = "grants_data.xlsx"
215
  file_type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
 
216
  download_link_html = f"<a href='data:{file_type};base64,{base64.b64encode(file_data).decode()}' download='{file_name}'><button style='background-color:#4CAF50;color:white;padding:10px 15px;border:none;border-radius:4px;'>⬇️ Download {selected_format}</button></a>"
217
  st.sidebar.markdown(download_link_html, unsafe_allow_html=True)
 
218
  shareable_link = get_shareable_link(file_data, file_name, file_type)
219
  whatsapp_url = f"https://api.whatsapp.com/send?text={urllib.parse.quote(f'Check out these grant opportunities: {shareable_link}')}"
220
  email_subject = urllib.parse.quote("Grant Opportunities File")
221
  email_body = urllib.parse.quote(f"Download the grant opportunities file here: {shareable_link}")
222
  email_url = f"mailto:?subject={email_subject}&body={email_body}"
 
223
  st.sidebar.markdown("<div style='margin-top:10px;'>Share via:</div>", unsafe_allow_html=True)
224
  st.sidebar.markdown(f"πŸ“± [WhatsApp]({whatsapp_url}) | πŸ“§ [Email]({email_url})", unsafe_allow_html=True)
225
 
 
231
  st.session_state.chat_history = []
232
  st.sidebar.success("Knowledge base loaded!")
233
 
234
+ # Main area: Data Preview
 
 
 
 
 
 
 
 
 
 
 
 
235
  st.markdown("---")
236
  if st.session_state.scraped_data and st.session_state.scraped_data.get('grants'):
237
  st.header("πŸ“Š Found Grant Data")
238
  with st.expander(f"πŸ“Š Preview Grant Data ({len(st.session_state.scraped_data['grants'])} grants)"):
239
  st.dataframe(st.session_state.scraped_data["grants"])
240
 
241
+ # Main area: Chat UI (shown if knowledge base is loaded)
242
+ if st.session_state.get("chat_interface_active"):
243
+ st.header("πŸ’¬ Chat with Grants Bot")
244
+ query = st.text_input("Your question:", key="chat_input_main")
245
+ if query:
246
+ with st.spinner("Generating response..."):
247
+ response = chat_with_knowledge_base(query)
248
+ answer = response["answer"] if isinstance(response, dict) and "answer" in response else response
249
+ st.session_state.chat_history.append({"query": query, "response": answer})
250
  if st.session_state.chat_history:
251
  st.subheader("Chat History")
252
  for chat in st.session_state.chat_history: