Anupam007 commited on
Commit
213d697
·
verified ·
1 Parent(s): 3b48fd3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -95
app.py CHANGED
@@ -1,10 +1,11 @@
1
- # Step 1: Import libraries (Ensure these are in requirements.txt)
2
  import gradio as gr
3
  import google.generativeai as genai
4
  from duckduckgo_search import DDGS
5
  import os
6
  import textwrap
7
- import traceback # For detailed error logging if needed
 
8
 
9
  # --- Step 2: Configure API Key (Using Hugging Face Secrets) ---
10
  is_api_configured = False
@@ -12,41 +13,38 @@ GOOGLE_API_KEY = None
12
 
13
  print("⚙️ Attempting to configure Google API Key from HF Space secret...")
14
  try:
15
- # Read the secret value set in the Hugging Face Space settings
16
  GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY')
17
-
18
  if GOOGLE_API_KEY:
19
  genai.configure(api_key=GOOGLE_API_KEY)
20
  print("✅ Google API Key configured successfully from HF secret.")
21
- is_api_configured = True # Set flag to True ONLY if configure() succeeds
22
  else:
23
- # Secret variable not found or empty in HF Space settings
24
  print("❌ Error: GOOGLE_API_KEY secret not found or is empty in Space settings.")
25
- print("➡️ Please go to your Space Settings -> Secrets and ensure 'GOOGLE_API_KEY' is added with your API key value.")
26
  is_api_configured = False
27
-
28
  except Exception as e:
29
  print(f"❌ An unexpected error occurred during API Key configuration: {e}")
30
- is_api_configured = False # Not configured if any other error occurs
31
- traceback.print_exc() # Print detailed traceback in HF logs for debugging
32
 
33
  # --- End of API Key Configuration ---
34
 
35
 
36
  # Step 3: Define Helper Functions
37
 
38
- # Function to perform web search
39
- def search_web(query, num_results=7):
40
  """Searches the web using DuckDuckGo and returns formatted results."""
41
- print(f"🔍 Searching the web for: '{query}'...")
42
  try:
43
- with DDGS() as ddgs:
 
44
  results = list(ddgs.text(query, region='wt-wt', safesearch='off', max_results=num_results))
45
  if not results:
46
  print("⚠️ No search results found.")
47
  return "No relevant search results found for the query."
48
 
49
- # Format results for the LLM
50
  context = f"Search results for query '{query}':\n\n"
51
  for i, result in enumerate(results):
52
  context += f"Source [{i+1}]: {result.get('title', 'N/A')}\n"
@@ -59,49 +57,40 @@ def search_web(query, num_results=7):
59
  except Exception as e:
60
  print(f"❌ Error during web search: {e}")
61
  traceback.print_exc() # Log details in HF
62
- return f"Error occurred during web search. Details: {e}"
 
 
 
 
63
 
64
  # Function to generate the case study using Gemini
65
  def generate_case_study(topic, search_context):
66
  """Generates a case study using Gemini based on the topic and search context."""
67
  print(f"🤖 Generating case study for: '{topic}'...")
68
 
69
- # --- Check 1: API Configuration ---
70
  if not is_api_configured:
71
- print("❌ Cannot generate: Google API Key not configured successfully.")
72
- # Provide error message tailored for HF environment
73
- return "Error: Google API Key not configured successfully. Please check the GOOGLE_API_KEY secret in your Hugging Face Space settings and ensure it's correct. The space might need a restart after setting the secret."
74
 
75
- # --- Check 2: Search Results ---
76
  if "Error occurred during web search" in search_context or "No relevant search results found" in search_context:
77
  print(f"❌ Cannot generate: Problem with search results.")
78
  return f"Cannot generate case study due to search issues:\n{search_context}"
79
 
80
- # --- Configure the Gemini model ---
81
  model_name = 'gemini-1.5-flash-latest'
82
  try:
83
  print(f" Using model: {model_name}")
84
  model = genai.GenerativeModel(model_name)
85
  except Exception as e:
86
  print(f"❌ Error initializing GenerativeModel '{model_name}': {e}")
87
- traceback.print_exc() # Log details in HF
88
- # Try to list available models if initialization fails
89
  error_message = f"Error setting up the AI model '{model_name}': {e}."
90
- try:
91
- available_models = [m.name for m in genai.list_models() if 'generateContent' in m.supported_generation_methods]
92
- print(f" Available models supporting generateContent: {available_models}")
93
- if available_models:
94
- suggested_model = next((m for m in available_models if 'flash' in m or 'pro' in m), available_models[0])
95
- error_message += f" You could try updating the model name in app.py to one of these like: '{suggested_model.split('/')[-1]}'"
96
- else:
97
- error_message += " Additionally, no compatible models were found via ListModels."
98
- except Exception as list_e:
99
- print(f" Additionally failed to list available models: {list_e}")
100
- error_message += " Failed to list alternative models."
101
  return error_message
102
 
103
-
104
- # --- Define the Prompt ---
105
  prompt = f"""
106
  You are an expert business analyst and case study writer.
107
  Your task is to generate a comprehensive case study based on the following topic: "{topic}"
@@ -110,22 +99,22 @@ def generate_case_study(topic, search_context):
110
 
111
  **Required Case Study Format:**
112
 
113
- **1. Title:** Create a concise and informative title based on the topic and findings.
114
- **2. Introduction/Executive Summary:** Briefly introduce the subject and the core topic. State the key outcome *mentioned in the sources*.
115
- **3. The Company/Subject:** Provide background information *only from the search results*.
116
- **4. The Challenge/Problem:** Describe the specific business issue mentioned in the sources.
117
- **5. The Solution:** Detail the implemented solution *based only on the sources*.
118
- **6. Implementation/Process:** (Optional) Describe *only if information is available in the sources*.
119
- **7. Results/Impact:** Quantify results and impact using data *from the sources*. If no results are mentioned, state that.
120
- **8. Conclusion:** Summarize key takeaways *based on the provided information*.
121
- **9. Sources:** List the URLs (`URL:` lines) from the search results that were most relevant.
122
 
123
  **Instructions:**
124
- * Adhere strictly to the format above. Use Markdown `##` for section headings.
125
- * Base your writing ***exclusively*** on the information in the "Provided Search Context". Do not invent information.
126
- * If details for a section are missing in the sources, explicitly state: "Information not available in the provided sources."
127
- * Maintain an objective and professional tone.
128
- * Format the output using Markdown.
129
 
130
  **Provided Search Context:**
131
  ---
@@ -135,103 +124,113 @@ def generate_case_study(topic, search_context):
135
  Now, please generate the case study for "{topic}".
136
  """
137
 
138
- # --- Generate Content ---
139
  try:
140
  response = model.generate_content(prompt)
141
-
142
- # --- Process Response Safely ---
143
  if response.parts:
144
  generated_text = "".join(part.text for part in response.parts)
145
  print("✅ Case study generated successfully.")
146
  return generated_text
147
  elif response.prompt_feedback and response.prompt_feedback.block_reason:
148
  block_reason = response.prompt_feedback.block_reason
149
- safety_info = f" Ratings: {response.prompt_feedback.safety_ratings}" if response.prompt_feedback.safety_ratings else ""
150
  print(f"⚠️ Generation blocked due to: {block_reason}")
151
- return f"Error: Generation failed. Blocked due to '{block_reason}'.{safety_info} Please try refining your topic or check content policies."
152
  elif not response.candidates:
153
  finish_reason = response.candidates[0].finish_reason if response.candidates else "UNKNOWN"
154
- print(f"⚠️ Warning: Generation finished without valid content (Finish Reason: {finish_reason}).")
155
- return f"Error: The AI model finished generation but produced no usable content (Reason: {finish_reason}). Check model compatibility or prompt complexity."
156
  else:
157
- print("⚠️ Warning: Generation finished but produced no text content for unknown reasons.")
158
- return "Error: The AI model generated an empty response. This might be due to input, filters, or a temporary issue."
159
 
160
  except Exception as e:
161
  print(f"❌ Error during case study generation: {e}")
162
- traceback.print_exc() # Log details in HF
163
  error_message = f"An unexpected error occurred during AI generation: {e}"
164
- # Add specific error checks relevant to Gemini API
165
- if "API key not valid" in str(e) or "PermissionDenied" in str(e) or "AuthenticationError" in str(e):
166
- error_message = "Error: Invalid, expired, or missing API Key. Please double-check the GOOGLE_API_KEY secret in Space settings and ensure the Gemini API is enabled in your Google Cloud project."
167
  elif "Model not found" in str(e):
168
- error_message = f"Error: The AI model ('{model_name}') was not found or is unsupported. Check the model name in app.py or try updating the google-generativeai library in requirements.txt."
169
  elif "Resource has been exhausted" in str(e) or "Quota" in str(e):
170
- error_message = "Error: API quota exceeded. Check your usage limits in Google Cloud Console."
171
- elif hasattr(e, 'message') and str(e) != e.message:
172
- error_message = f"Error during AI generation: {e.message} (Details: {e})"
173
  return error_message
174
 
175
 
176
- # Step 4: Define the main processing function for Gradio
177
  def create_case_study(company_or_topic):
178
- """Orchestrates the web search and case study generation process."""
179
- print("-" * 60) # Separator for new request
180
  if not company_or_topic or not company_or_topic.strip():
181
- print("⚠️ Input validation failed: Empty topic received.")
182
  return "Please enter a valid company name or topic."
183
 
184
  cleaned_topic = company_or_topic.strip()
185
  print(f"➡️ Processing request for: '{cleaned_topic}'")
186
 
187
- # 1. Search the web
188
- search_results_context = search_web(cleaned_topic)
189
-
190
- # 2. Generate the case study (handles API key/search errors internally)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  case_study_markdown = generate_case_study(cleaned_topic, search_results_context)
192
 
193
- print("-" * 60) # Separator for end of request
194
  return case_study_markdown
195
 
196
  # Step 5: Create and Launch the Gradio Interface
197
  print("\n⚙️ Setting up Gradio interface...")
198
 
199
- # Add a final check before defining Gradio Interface (optional but good practice)
200
  if not is_api_configured:
201
- print("\n" + "="*60)
202
- print("‼️ WARNING: Google API Key not configured successfully at startup. ‼️")
203
- print(" The Gradio interface will launch, but case study generation WILL FAIL until the API key is correctly set in secrets and the space potentially restarted.")
204
- print("="*60 + "\n")
205
 
206
- # Define the Gradio interface
207
  iface = gr.Interface(
208
  fn=create_case_study,
209
  inputs=gr.Textbox(
210
  lines=2,
211
- placeholder="Enter a company name or topic (e.g., 'Acme Corp uses AI for customer support' or 'History of Netflix recommendation engine')",
212
  label="Company Name or Topic"
213
  ),
214
- outputs=gr.Markdown( # Use Markdown output for better formatting
215
- label="Generated Case Study"
216
- ),
217
  title="📄 AI Case Study Generator (Gemini + DuckDuckGo)",
218
- description="Enter a company/topic. The app searches the web (DuckDuckGo) and uses Google's Gemini AI to write a case study *based only on the search results*. \n**Requires a correctly configured `GOOGLE_API_KEY` secret in Hugging Face Space Settings.**",
219
  allow_flagging="never",
220
  examples=[
221
  ["How Spotify uses AI for music recommendations"],
222
  ["Tesla Autopilot development challenges"],
223
  ["Use of AI in drug discovery by Pfizer"],
224
- ["Environmental impact reduction using AI at Google data centers"],
225
  ],
226
- theme=gr.themes.Soft() # Optional: Apply a soft theme
227
  )
228
 
229
  print("🚀 Launching Gradio interface...")
230
-
231
- # Launch the interface (share=True is not needed on HF Spaces)
232
- # Use debug=True for more detailed logs initially, you can remove it later
233
  try:
234
- iface.launch(debug=True)
 
235
  except Exception as e:
236
  print(f"❌ Failed to launch Gradio interface: {e}")
237
- traceback.print_exc() # Log details in HF
 
1
+ # Step 1: Import libraries
2
  import gradio as gr
3
  import google.generativeai as genai
4
  from duckduckgo_search import DDGS
5
  import os
6
  import textwrap
7
+ import traceback # For detailed error logging
8
+ import time # For retry delay
9
 
10
  # --- Step 2: Configure API Key (Using Hugging Face Secrets) ---
11
  is_api_configured = False
 
13
 
14
  print("⚙️ Attempting to configure Google API Key from HF Space secret...")
15
  try:
 
16
  GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY')
 
17
  if GOOGLE_API_KEY:
18
  genai.configure(api_key=GOOGLE_API_KEY)
19
  print("✅ Google API Key configured successfully from HF secret.")
20
+ is_api_configured = True
21
  else:
 
22
  print("❌ Error: GOOGLE_API_KEY secret not found or is empty in Space settings.")
23
+ print("➡️ Please go to your Space Settings -> Secrets and ensure 'GOOGLE_API_KEY' is added.")
24
  is_api_configured = False
 
25
  except Exception as e:
26
  print(f"❌ An unexpected error occurred during API Key configuration: {e}")
27
+ is_api_configured = False
28
+ traceback.print_exc()
29
 
30
  # --- End of API Key Configuration ---
31
 
32
 
33
  # Step 3: Define Helper Functions
34
 
35
+ # Function to perform web search (with increased timeout)
36
+ def search_web(query, num_results=7, search_timeout=20): # Added timeout parameter
37
  """Searches the web using DuckDuckGo and returns formatted results."""
38
+ print(f"🔍 Searching the web for: '{query}' (Timeout: {search_timeout}s)...")
39
  try:
40
+ # Increase the timeout when initializing DDGS
41
+ with DDGS(timeout=search_timeout) as ddgs:
42
  results = list(ddgs.text(query, region='wt-wt', safesearch='off', max_results=num_results))
43
  if not results:
44
  print("⚠️ No search results found.")
45
  return "No relevant search results found for the query."
46
 
47
+ # Format results
48
  context = f"Search results for query '{query}':\n\n"
49
  for i, result in enumerate(results):
50
  context += f"Source [{i+1}]: {result.get('title', 'N/A')}\n"
 
57
  except Exception as e:
58
  print(f"❌ Error during web search: {e}")
59
  traceback.print_exc() # Log details in HF
60
+ # Make error message more specific for timeouts
61
+ error_detail = f"Details: {e}"
62
+ if "timed out" in str(e):
63
+ error_detail = f"Details: The connection to the search engine timed out after {search_timeout} seconds. This might be due to temporary network issues. Error: {e}"
64
+ return f"Error occurred during web search. {error_detail}"
65
 
66
  # Function to generate the case study using Gemini
67
  def generate_case_study(topic, search_context):
68
  """Generates a case study using Gemini based on the topic and search context."""
69
  print(f"🤖 Generating case study for: '{topic}'...")
70
 
71
+ # Check 1: API Configuration
72
  if not is_api_configured:
73
+ print("❌ Cannot generate: Google API Key not configured.")
74
+ return "Error: Google API Key not configured successfully. Check HF Space secrets."
 
75
 
76
+ # Check 2: Search Results Validity
77
  if "Error occurred during web search" in search_context or "No relevant search results found" in search_context:
78
  print(f"❌ Cannot generate: Problem with search results.")
79
  return f"Cannot generate case study due to search issues:\n{search_context}"
80
 
81
+ # Configure the Gemini model
82
  model_name = 'gemini-1.5-flash-latest'
83
  try:
84
  print(f" Using model: {model_name}")
85
  model = genai.GenerativeModel(model_name)
86
  except Exception as e:
87
  print(f"❌ Error initializing GenerativeModel '{model_name}': {e}")
88
+ traceback.print_exc()
 
89
  error_message = f"Error setting up the AI model '{model_name}': {e}."
90
+ # (Optional: Add model listing code back here if needed for debugging)
 
 
 
 
 
 
 
 
 
 
91
  return error_message
92
 
93
+ # Define the Prompt (Keep your detailed prompt here)
 
94
  prompt = f"""
95
  You are an expert business analyst and case study writer.
96
  Your task is to generate a comprehensive case study based on the following topic: "{topic}"
 
99
 
100
  **Required Case Study Format:**
101
 
102
+ **1. Title:** Create a concise and informative title.
103
+ **2. Introduction/Executive Summary:** Briefly introduce the subject and core topic. State key outcome from sources.
104
+ **3. The Company/Subject:** Background info from search results only.
105
+ **4. The Challenge/Problem:** Specific issue mentioned in sources.
106
+ **5. The Solution:** Implemented solution based only on sources.
107
+ **6. Implementation/Process:** (Optional) Describe only if available in sources.
108
+ **7. Results/Impact:** Quantify results using data from sources. State if none mentioned.
109
+ **8. Conclusion:** Summarize key takeaways based on provided info.
110
+ **9. Sources:** List relevant URLs from search results.
111
 
112
  **Instructions:**
113
+ * Adhere strictly to the format (use Markdown `##`).
114
+ * Base writing ***exclusively*** on "Provided Search Context". Do not invent.
115
+ * If details missing, state: "Information not available in the provided sources."
116
+ * Maintain objective tone.
117
+ * Format using Markdown.
118
 
119
  **Provided Search Context:**
120
  ---
 
124
  Now, please generate the case study for "{topic}".
125
  """
126
 
127
+ # Generate Content
128
  try:
129
  response = model.generate_content(prompt)
130
+ # Process Response Safely (Keep the detailed checking from previous version)
 
131
  if response.parts:
132
  generated_text = "".join(part.text for part in response.parts)
133
  print("✅ Case study generated successfully.")
134
  return generated_text
135
  elif response.prompt_feedback and response.prompt_feedback.block_reason:
136
  block_reason = response.prompt_feedback.block_reason
 
137
  print(f"⚠️ Generation blocked due to: {block_reason}")
138
+ return f"Error: Generation failed. Blocked due to '{block_reason}'. Check content policies."
139
  elif not response.candidates:
140
  finish_reason = response.candidates[0].finish_reason if response.candidates else "UNKNOWN"
141
+ print(f"⚠️ Generation finished without valid content (Reason: {finish_reason}).")
142
+ return f"Error: AI model finished but produced no usable content (Reason: {finish_reason})."
143
  else:
144
+ print("⚠️ Generation produced no text content.")
145
+ return "Error: AI model generated an empty response."
146
 
147
  except Exception as e:
148
  print(f"❌ Error during case study generation: {e}")
149
+ traceback.print_exc()
150
  error_message = f"An unexpected error occurred during AI generation: {e}"
151
+ # Add specific error checks (keep from previous version)
152
+ if "API key not valid" in str(e) or "PermissionDenied" in str(e):
153
+ error_message = "Error: Invalid/Missing API Key. Check GOOGLE_API_KEY secret and Gemini API enablement."
154
  elif "Model not found" in str(e):
155
+ error_message = f"Error: AI model ('{model_name}') not found/unsupported."
156
  elif "Resource has been exhausted" in str(e) or "Quota" in str(e):
157
+ error_message = "Error: API quota exceeded. Check Google Cloud Console."
 
 
158
  return error_message
159
 
160
 
161
+ # Step 4: Define the main processing function (with search retries)
162
  def create_case_study(company_or_topic):
163
+ """Orchestrates the web search (with retries) and case study generation."""
164
+ print("-" * 60)
165
  if not company_or_topic or not company_or_topic.strip():
166
+ print("⚠️ Input validation failed: Empty topic.")
167
  return "Please enter a valid company name or topic."
168
 
169
  cleaned_topic = company_or_topic.strip()
170
  print(f"➡️ Processing request for: '{cleaned_topic}'")
171
 
172
+ # --- Search with Retries ---
173
+ search_results_context = None
174
+ max_retries = 2 # Total attempts = 1 (initial) + max_retries
175
+ retry_delay_seconds = 3
176
+ search_timeout_seconds = 25 # You can adjust this timeout specifically for search
177
+
178
+ for attempt in range(max_retries + 1):
179
+ print(f" Attempting web search ({attempt + 1}/{max_retries + 1})...")
180
+ search_results_context = search_web(cleaned_topic, search_timeout=search_timeout_seconds)
181
+
182
+ # Check if search was successful
183
+ if search_results_context and "Error occurred during web search" not in search_results_context:
184
+ print(" Web search successful.")
185
+ break # Exit loop on success
186
+
187
+ # If search failed and retries remain
188
+ if attempt < max_retries:
189
+ print(f" Search attempt failed. Waiting {retry_delay_seconds}s before retrying...")
190
+ time.sleep(retry_delay_seconds)
191
+ else:
192
+ # Max retries reached
193
+ print(f" Search failed after {max_retries + 1} attempts.")
194
+ # Return the error from the last attempt directly
195
+ print("-" * 60)
196
+ return f"Failed to retrieve search results after multiple attempts.\nLast error: {search_results_context}"
197
+
198
+ # --- Generate Case Study (only if search succeeded) ---
199
+ # This part is reached only if the loop above 'break's (i.e., search succeeded)
200
  case_study_markdown = generate_case_study(cleaned_topic, search_results_context)
201
 
202
+ print("-" * 60)
203
  return case_study_markdown
204
 
205
  # Step 5: Create and Launch the Gradio Interface
206
  print("\n⚙️ Setting up Gradio interface...")
207
 
 
208
  if not is_api_configured:
209
+ print("\n" + "="*60 + "\n‼️ WARNING: API Key not configured at startup. Generation will fail. Check Secrets.\n" + "="*60 + "\n")
 
 
 
210
 
 
211
  iface = gr.Interface(
212
  fn=create_case_study,
213
  inputs=gr.Textbox(
214
  lines=2,
215
+ placeholder="Enter a company name or topic (e.g., 'Acme Corp uses AI for customer support')",
216
  label="Company Name or Topic"
217
  ),
218
+ outputs=gr.Markdown(label="Generated Case Study"),
 
 
219
  title="📄 AI Case Study Generator (Gemini + DuckDuckGo)",
220
+ description="Enter a topic. The app searches the web (DDG) and uses Gemini AI to write a case study based *only* on the search results.\n**Requires `GOOGLE_API_KEY` secret in HF Space Settings.**",
221
  allow_flagging="never",
222
  examples=[
223
  ["How Spotify uses AI for music recommendations"],
224
  ["Tesla Autopilot development challenges"],
225
  ["Use of AI in drug discovery by Pfizer"],
 
226
  ],
227
+ theme=gr.themes.Soft()
228
  )
229
 
230
  print("🚀 Launching Gradio interface...")
 
 
 
231
  try:
232
+ # Removed debug=True for potentially cleaner logs in production, add back if needed
233
+ iface.launch()
234
  except Exception as e:
235
  print(f"❌ Failed to launch Gradio interface: {e}")
236
+ traceback.print_exc()