Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -14,7 +14,7 @@ st.set_page_config(
|
|
| 14 |
layout="wide"
|
| 15 |
)
|
| 16 |
|
| 17 |
-
# Initialize Gemini with better error handling
|
| 18 |
@st.cache_resource
|
| 19 |
def init_gemini():
|
| 20 |
try:
|
|
@@ -40,25 +40,75 @@ def init_gemini():
|
|
| 40 |
except:
|
| 41 |
pass
|
| 42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
if api_key and api_key.strip():
|
|
|
|
| 44 |
genai.configure(api_key=api_key.strip())
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
# Test the model with a simple query to verify it works
|
| 48 |
try:
|
| 49 |
-
test_response = model.generate_content(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
if test_response and test_response.text:
|
|
|
|
| 51 |
return model
|
| 52 |
except Exception as e:
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
return None
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
-
return None
|
| 57 |
except ImportError:
|
| 58 |
-
st.error("Google Generative AI
|
| 59 |
return None
|
| 60 |
except Exception as e:
|
| 61 |
-
st.
|
| 62 |
return None
|
| 63 |
|
| 64 |
# Data processing functions
|
|
@@ -193,7 +243,7 @@ def create_plots(df):
|
|
| 193 |
return plots
|
| 194 |
|
| 195 |
def query_llm(model, data_summary, user_question):
|
| 196 |
-
"""Query Gemini with production data context"""
|
| 197 |
if not model:
|
| 198 |
return "AI Assistant is not available. Please check API configuration."
|
| 199 |
|
|
@@ -215,32 +265,62 @@ def query_llm(model, data_summary, user_question):
|
|
| 215 |
|
| 216 |
context += f"\nUser Question: {user_question}\n\nPlease provide a concise, data-driven answer based on this production data."
|
| 217 |
|
| 218 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
response = model.generate_content(
|
| 220 |
context,
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
'top_p': 0.8,
|
| 224 |
-
'top_k': 40,
|
| 225 |
-
'max_output_tokens': 1024,
|
| 226 |
-
}
|
| 227 |
)
|
| 228 |
|
| 229 |
if response and response.text:
|
| 230 |
return response.text
|
|
|
|
|
|
|
| 231 |
else:
|
| 232 |
-
return "No response received from
|
| 233 |
|
| 234 |
except Exception as e:
|
| 235 |
error_msg = str(e).lower()
|
| 236 |
if "403" in error_msg or "forbidden" in error_msg:
|
| 237 |
-
return "
|
| 238 |
-
elif "quota" in error_msg:
|
| 239 |
-
return "
|
| 240 |
elif "timeout" in error_msg:
|
| 241 |
-
return "
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
else:
|
| 243 |
-
return f"AI service error: {str(e)}"
|
| 244 |
|
| 245 |
# Load data with better error handling
|
| 246 |
def load_data(uploaded_file):
|
|
@@ -277,22 +357,56 @@ def main():
|
|
| 277 |
uploaded_file = st.file_uploader("Choose CSV file", type=['csv'])
|
| 278 |
|
| 279 |
if model:
|
| 280 |
-
st.success("🤖 AI Assistant Ready")
|
| 281 |
else:
|
| 282 |
-
st.warning("⚠️ AI Assistant unavailable")
|
| 283 |
-
with st.expander("API Configuration Help"):
|
| 284 |
st.markdown("""
|
| 285 |
-
|
| 286 |
-
1. Get a Google AI API key from https://ai.google.dev/
|
| 287 |
-
2. Add it to your Streamlit secrets as `GOOGLE_API_KEY`
|
| 288 |
-
3. Or set it as environment variable `GOOGLE_API_KEY`
|
| 289 |
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
""")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 296 |
|
| 297 |
if uploaded_file is not None:
|
| 298 |
# Load and process data
|
|
|
|
| 14 |
layout="wide"
|
| 15 |
)
|
| 16 |
|
| 17 |
+
# Initialize Gemini 1.5 Pro with better error handling
|
| 18 |
@st.cache_resource
|
| 19 |
def init_gemini():
|
| 20 |
try:
|
|
|
|
| 40 |
except:
|
| 41 |
pass
|
| 42 |
|
| 43 |
+
# Method 4: Direct input fallback
|
| 44 |
+
if not api_key:
|
| 45 |
+
try:
|
| 46 |
+
api_key = st.secrets.get("api_key", "")
|
| 47 |
+
except:
|
| 48 |
+
pass
|
| 49 |
+
|
| 50 |
if api_key and api_key.strip():
|
| 51 |
+
# Configure with API key
|
| 52 |
genai.configure(api_key=api_key.strip())
|
| 53 |
+
|
| 54 |
+
# Use Gemini 1.5 Pro model
|
| 55 |
+
model = genai.GenerativeModel('gemini-1.5-pro-latest')
|
| 56 |
+
|
| 57 |
+
# Configure safety settings to avoid blocking
|
| 58 |
+
safety_settings = [
|
| 59 |
+
{
|
| 60 |
+
"category": "HARM_CATEGORY_HARASSMENT",
|
| 61 |
+
"threshold": "BLOCK_NONE"
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"category": "HARM_CATEGORY_HATE_SPEECH",
|
| 65 |
+
"threshold": "BLOCK_NONE"
|
| 66 |
+
},
|
| 67 |
+
{
|
| 68 |
+
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
| 69 |
+
"threshold": "BLOCK_NONE"
|
| 70 |
+
},
|
| 71 |
+
{
|
| 72 |
+
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
|
| 73 |
+
"threshold": "BLOCK_NONE"
|
| 74 |
+
}
|
| 75 |
+
]
|
| 76 |
|
| 77 |
# Test the model with a simple query to verify it works
|
| 78 |
try:
|
| 79 |
+
test_response = model.generate_content(
|
| 80 |
+
"Hello, respond with 'Gemini 1.5 Pro API working'",
|
| 81 |
+
safety_settings=safety_settings,
|
| 82 |
+
generation_config={
|
| 83 |
+
'temperature': 0.1,
|
| 84 |
+
'top_p': 0.8,
|
| 85 |
+
'top_k': 40,
|
| 86 |
+
'max_output_tokens': 100,
|
| 87 |
+
}
|
| 88 |
+
)
|
| 89 |
if test_response and test_response.text:
|
| 90 |
+
st.success(f"✅ {test_response.text}")
|
| 91 |
return model
|
| 92 |
except Exception as e:
|
| 93 |
+
error_msg = str(e).lower()
|
| 94 |
+
if "403" in error_msg:
|
| 95 |
+
st.error("❌ API Key 权限不足 - 请检查 Google AI Studio 中的 API 设置")
|
| 96 |
+
elif "quota" in error_msg:
|
| 97 |
+
st.error("❌ API 配额已用完 - 请检查使用限制")
|
| 98 |
+
elif "billing" in error_msg:
|
| 99 |
+
st.error("❌ 需要启用计费 - Gemini 1.5 Pro 可能需要付费账户")
|
| 100 |
+
else:
|
| 101 |
+
st.error(f"❌ 模型测试失败: {str(e)}")
|
| 102 |
return None
|
| 103 |
+
else:
|
| 104 |
+
st.warning("⚠️ 未找到 GOOGLE_API_KEY")
|
| 105 |
+
return None
|
| 106 |
|
|
|
|
| 107 |
except ImportError:
|
| 108 |
+
st.error("❌ Google Generative AI 库未安装")
|
| 109 |
return None
|
| 110 |
except Exception as e:
|
| 111 |
+
st.error(f"❌ 初始化 Gemini 时出错: {str(e)}")
|
| 112 |
return None
|
| 113 |
|
| 114 |
# Data processing functions
|
|
|
|
| 243 |
return plots
|
| 244 |
|
| 245 |
def query_llm(model, data_summary, user_question):
|
| 246 |
+
"""Query Gemini 1.5 Pro with production data context"""
|
| 247 |
if not model:
|
| 248 |
return "AI Assistant is not available. Please check API configuration."
|
| 249 |
|
|
|
|
| 265 |
|
| 266 |
context += f"\nUser Question: {user_question}\n\nPlease provide a concise, data-driven answer based on this production data."
|
| 267 |
|
| 268 |
+
# Configure safety settings for Gemini 1.5 Pro
|
| 269 |
+
safety_settings = [
|
| 270 |
+
{
|
| 271 |
+
"category": "HARM_CATEGORY_HARASSMENT",
|
| 272 |
+
"threshold": "BLOCK_NONE"
|
| 273 |
+
},
|
| 274 |
+
{
|
| 275 |
+
"category": "HARM_CATEGORY_HATE_SPEECH",
|
| 276 |
+
"threshold": "BLOCK_NONE"
|
| 277 |
+
},
|
| 278 |
+
{
|
| 279 |
+
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
|
| 280 |
+
"threshold": "BLOCK_NONE"
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
|
| 284 |
+
"threshold": "BLOCK_NONE"
|
| 285 |
+
}
|
| 286 |
+
]
|
| 287 |
+
|
| 288 |
+
# Gemini 1.5 Pro generation config
|
| 289 |
+
generation_config = {
|
| 290 |
+
'temperature': 0.2,
|
| 291 |
+
'top_p': 0.8,
|
| 292 |
+
'top_k': 40,
|
| 293 |
+
'max_output_tokens': 2048,
|
| 294 |
+
'candidate_count': 1
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
response = model.generate_content(
|
| 298 |
context,
|
| 299 |
+
safety_settings=safety_settings,
|
| 300 |
+
generation_config=generation_config
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
)
|
| 302 |
|
| 303 |
if response and response.text:
|
| 304 |
return response.text
|
| 305 |
+
elif response and hasattr(response, 'candidates') and response.candidates:
|
| 306 |
+
return "Response was blocked by safety filters. Please try rephrasing your question."
|
| 307 |
else:
|
| 308 |
+
return "No response received from Gemini 1.5 Pro."
|
| 309 |
|
| 310 |
except Exception as e:
|
| 311 |
error_msg = str(e).lower()
|
| 312 |
if "403" in error_msg or "forbidden" in error_msg:
|
| 313 |
+
return "❌ API access denied. Please check:\n1. API Key validity\n2. Gemini API is enabled\n3. Account has sufficient permissions"
|
| 314 |
+
elif "quota" in error_msg or "resource_exhausted" in error_msg:
|
| 315 |
+
return "❌ API quota exceeded. Please try again later or upgrade your account."
|
| 316 |
elif "timeout" in error_msg:
|
| 317 |
+
return "⏱️ Request timeout. Please try again."
|
| 318 |
+
elif "billing" in error_msg:
|
| 319 |
+
return "💳 Billing account required for Gemini 1.5 Pro."
|
| 320 |
+
elif "safety" in error_msg:
|
| 321 |
+
return "🛡️ Content blocked by safety filters. Please rephrase your question."
|
| 322 |
else:
|
| 323 |
+
return f"❌ AI service error: {str(e)}"
|
| 324 |
|
| 325 |
# Load data with better error handling
|
| 326 |
def load_data(uploaded_file):
|
|
|
|
| 357 |
uploaded_file = st.file_uploader("Choose CSV file", type=['csv'])
|
| 358 |
|
| 359 |
if model:
|
| 360 |
+
st.success("🤖 Gemini 1.5 Pro AI Assistant Ready")
|
| 361 |
else:
|
| 362 |
+
st.warning("⚠️ Gemini 1.5 Pro AI Assistant unavailable")
|
| 363 |
+
with st.expander("🔧 API Configuration Help"):
|
| 364 |
st.markdown("""
|
| 365 |
+
**Steps to enable Gemini 1.5 Pro:**
|
|
|
|
|
|
|
|
|
|
| 366 |
|
| 367 |
+
1. **Get API Key**:
|
| 368 |
+
- Visit [Google AI Studio](https://aistudio.google.com/app/apikey)
|
| 369 |
+
- Create a new API Key
|
| 370 |
+
|
| 371 |
+
2. **Set API Key**:
|
| 372 |
+
```bash
|
| 373 |
+
# Environment variable
|
| 374 |
+
export GOOGLE_API_KEY="your_api_key_here"
|
| 375 |
+
```
|
| 376 |
+
Or in Streamlit secrets.toml:
|
| 377 |
+
```toml
|
| 378 |
+
GOOGLE_API_KEY = "your_api_key_here"
|
| 379 |
+
```
|
| 380 |
+
|
| 381 |
+
3. **Common 403 Error Causes**:
|
| 382 |
+
- ❌ Invalid or expired API Key
|
| 383 |
+
- ❌ Generative AI API not enabled
|
| 384 |
+
- ❌ Insufficient account permissions
|
| 385 |
+
- ❌ Billing account required (1.5 Pro may need payment)
|
| 386 |
+
- ❌ Geographic restrictions
|
| 387 |
+
|
| 388 |
+
4. **Solutions**:
|
| 389 |
+
- Verify API Key is correctly copied
|
| 390 |
+
- Enable API in Google Cloud Console
|
| 391 |
+
- Check account billing status
|
| 392 |
+
- Try VPN if geographic restrictions apply
|
| 393 |
""")
|
| 394 |
+
|
| 395 |
+
# API Key testing tool
|
| 396 |
+
st.markdown("**🧪 API Key Testing Tool**")
|
| 397 |
+
test_api_key = st.text_input("Enter your API Key to test:", type="password")
|
| 398 |
+
if st.button("Test API Key") and test_api_key:
|
| 399 |
+
try:
|
| 400 |
+
import google.generativeai as genai
|
| 401 |
+
genai.configure(api_key=test_api_key)
|
| 402 |
+
test_model = genai.GenerativeModel('gemini-1.5-pro-latest')
|
| 403 |
+
test_response = test_model.generate_content("Test message")
|
| 404 |
+
if test_response.text:
|
| 405 |
+
st.success("✅ API Key works correctly!")
|
| 406 |
+
else:
|
| 407 |
+
st.error("❌ API Key test failed")
|
| 408 |
+
except Exception as e:
|
| 409 |
+
st.error(f"❌ Error: {str(e)}")
|
| 410 |
|
| 411 |
if uploaded_file is not None:
|
| 412 |
# Load and process data
|