rdune71 commited on
Commit
4f1a78a
·
1 Parent(s): 6f941c0

Fix Redis Cloud SSL connection, Streamlit version compatibility, and update requirements

Browse files
Files changed (3) hide show
  1. app.py +53 -53
  2. core/redis_client.py +14 -61
  3. requirements.txt +1 -1
app.py CHANGED
@@ -16,18 +16,25 @@ st.set_page_config(page_title="AI Life Coach", page_icon="🧠", layout="wide")
16
  # Initialize session state
17
  if "messages" not in st.session_state:
18
  st.session_state.messages = []
 
19
  if "last_error" not in st.session_state:
20
  st.session_state.last_error = ""
 
21
  if "last_ollama_call_success" not in st.session_state:
22
  st.session_state.last_ollama_call_success = None
 
23
  if "last_ollama_call_time" not in st.session_state:
24
  st.session_state.last_ollama_call_time = ""
 
25
  if "last_ollama_response_preview" not in st.session_state:
26
  st.session_state.last_ollama_response_preview = ""
 
27
  if "last_hf_call_success" not in st.session_state:
28
  st.session_state.last_hf_call_success = None
 
29
  if "last_hf_call_time" not in st.session_state:
30
  st.session_state.last_hf_call_time = ""
 
31
  if "last_hf_response_preview" not in st.session_state:
32
  st.session_state.last_hf_response_preview = ""
33
 
@@ -35,67 +42,68 @@ if "last_hf_response_preview" not in st.session_state:
35
  with st.sidebar:
36
  st.title("AI Life Coach")
37
  st.markdown("Your personal AI-powered life development assistant")
38
-
39
  # Model selection
40
  model_options = {
41
  "Mistral 7B (Local)": "mistral:latest",
42
  "Llama 2 7B (Local)": "llama2:latest",
43
  "OpenChat 3.5 (Local)": "openchat:latest"
44
  }
45
-
46
  selected_model_name = st.selectbox(
47
  "Select Model",
48
  options=list(model_options.keys()),
49
  index=0
50
  )
51
-
52
  st.session_state.selected_model = model_options[selected_model_name]
53
-
54
  # Ollama URL input
55
  st.session_state.ngrok_url = st.text_input(
56
  "Ollama Server URL",
57
  value=st.session_state.get("ngrok_url", "http://localhost:11434"),
58
  help="Enter the URL to your Ollama server"
59
  )
60
-
61
  # Conversation history
62
  st.subheader("Conversation History")
63
  if st.button("Clear History"):
64
  st.session_state.messages = []
65
  st.success("History cleared!")
66
-
67
  # Debug info
68
  with st.sidebar.expander("🔧 Debug Info"):
69
- st.write(f"**OLLAMA_HOST**: `{st.session_state.ngrok_url}`")
70
- st.write(f"**Selected Model**: `{st.session_state.selected_model}`")
71
- st.write(f"**Fallback Mode**: {'✅ On' if config.use_fallback else '❌ Off'}")
72
- st.write(f"**Redis Status**: {'✅ Healthy' if check_redis_health() else '⚠️ Unavailable'}")
73
- st.write(f"**Env Detected As**: {'☁️ HF Space' if config.is_hf_space else '🏠 Local'}")
74
- st.write(f"**HF Token Set**: {'✅ Yes' if config.hf_token else '❌ No'}")
 
75
  if st.session_state.last_error:
76
  st.warning(f"Last Error: {st.session_state.last_error}")
77
-
78
- # Ollama API Call Tracking
79
- if st.session_state.last_ollama_call_success is not None:
80
- status_icon = "✅ Success" if st.session_state.last_ollama_call_success else "❌ Failed"
81
- st.write(f"**Last Ollama Call**: {status_icon}")
82
- st.write(f"**At**: {st.session_state.last_ollama_call_time}")
83
- if st.session_state.last_ollama_response_preview:
84
- st.code(st.session_state.last_ollama_response_preview[:200] + ("..." if len(st.session_state.last_ollama_response_preview) > 200 else ""), language="text")
85
-
86
- # Hugging Face API Call Tracking
87
- if st.session_state.last_hf_call_success is not None:
88
- status_icon = "✅ Success" if st.session_state.last_hf_call_success else "❌ Failed"
89
- st.write(f"**Last HF Call**: {status_icon}")
90
- st.write(f"**At**: {st.session_state.last_hf_call_time}")
91
- if st.session_state.last_hf_response_preview:
92
- st.code(st.session_state.last_hf_response_preview[:200] + ("..." if len(st.session_state.last_hf_response_preview) > 200 else ""), language="text")
93
-
94
- # Manual Refresh Button
95
- if st.button("🔄 Refresh Ollama Status"):
96
- from services.ollama_monitor import check_ollama_status
97
- status = check_ollama_status()
98
- st.toast(f"Ollama Status: {'Running' if status['running'] else 'Unavailable'}", icon="📡")
 
 
99
 
100
  # Main chat interface
101
  st.title("🧠 AI Life Coach")
@@ -115,7 +123,6 @@ with col1:
115
  placeholder="Type your message here...",
116
  label_visibility="collapsed"
117
  )
118
-
119
  with col2:
120
  send_button = st.button("Send", key="send_message_button", use_container_width=True)
121
 
@@ -123,37 +130,34 @@ if send_button and user_input.strip():
123
  # Display user message
124
  with st.chat_message("user"):
125
  st.markdown(user_input)
126
-
127
  # Add user message to history
128
  st.session_state.messages.append({"role": "user", "content": user_input})
129
-
130
  # Reset error state
131
  st.session_state.last_error = ""
132
-
133
  # Get conversation history
134
  user_session = session_manager.get_session("default_user")
135
  conversation = user_session.get("conversation", [])
136
  conversation_history = conversation[-5:] # Last 5 messages
137
  conversation_history.append({"role": "user", "content": user_input})
138
-
139
  # Send to backend
140
  with st.chat_message("assistant"):
141
  with st.spinner("AI Coach is thinking..."):
142
  ai_response = None
143
  backend_used = ""
144
  error_msg = ""
145
-
146
  # Try Ollama first if not falling back
147
  if not config.use_fallback:
148
  try:
149
  ai_response = send_to_ollama(
150
- user_input,
151
- conversation_history,
152
- st.session_state.ngrok_url,
153
- st.session_state.selected_model
154
  )
155
  backend_used = "Ollama"
156
-
157
  # Capture success metadata
158
  st.session_state.last_ollama_call_success = True
159
  st.session_state.last_ollama_call_time = str(datetime.utcnow())
@@ -164,13 +168,12 @@ if send_button and user_input.strip():
164
  st.session_state.last_ollama_call_success = False
165
  st.session_state.last_ollama_call_time = str(datetime.utcnow())
166
  st.session_state.last_ollama_response_preview = str(e)[:200]
167
-
168
- # Fallback to Hugging Face
169
  if not ai_response and config.hf_token:
170
  try:
171
  ai_response = send_to_hf(user_input, conversation_history)
172
  backend_used = "Hugging Face"
173
-
174
  # Capture success metadata
175
  st.session_state.last_hf_call_success = True
176
  st.session_state.last_hf_call_time = str(datetime.utcnow())
@@ -181,23 +184,20 @@ if send_button and user_input.strip():
181
  st.session_state.last_hf_call_success = False
182
  st.session_state.last_hf_call_time = str(datetime.utcnow())
183
  st.session_state.last_hf_response_preview = str(e)[:200]
184
-
185
  if ai_response:
186
  st.markdown(f"{ai_response}")
187
-
188
  # Update conversation history
189
  conversation.append({"role": "user", "content": user_input})
190
  conversation.append({"role": "assistant", "content": ai_response})
191
-
192
  # Update session using the correct method
193
  user_session["conversation"] = conversation
194
  session_manager.update_session("default_user", user_session)
195
-
196
  # Add assistant response to history
197
  st.session_state.messages.append({"role": "assistant", "content": ai_response})
198
  else:
199
  st.error("Failed to get response from both providers.")
200
  st.session_state.last_error = error_msg or "No response from either provider"
201
-
202
  # Clear input by forcing rerun
203
  st.experimental_rerun()
 
16
  # Initialize session state
17
  if "messages" not in st.session_state:
18
  st.session_state.messages = []
19
+
20
  if "last_error" not in st.session_state:
21
  st.session_state.last_error = ""
22
+
23
  if "last_ollama_call_success" not in st.session_state:
24
  st.session_state.last_ollama_call_success = None
25
+
26
  if "last_ollama_call_time" not in st.session_state:
27
  st.session_state.last_ollama_call_time = ""
28
+
29
  if "last_ollama_response_preview" not in st.session_state:
30
  st.session_state.last_ollama_response_preview = ""
31
+
32
  if "last_hf_call_success" not in st.session_state:
33
  st.session_state.last_hf_call_success = None
34
+
35
  if "last_hf_call_time" not in st.session_state:
36
  st.session_state.last_hf_call_time = ""
37
+
38
  if "last_hf_response_preview" not in st.session_state:
39
  st.session_state.last_hf_response_preview = ""
40
 
 
42
  with st.sidebar:
43
  st.title("AI Life Coach")
44
  st.markdown("Your personal AI-powered life development assistant")
45
+
46
  # Model selection
47
  model_options = {
48
  "Mistral 7B (Local)": "mistral:latest",
49
  "Llama 2 7B (Local)": "llama2:latest",
50
  "OpenChat 3.5 (Local)": "openchat:latest"
51
  }
 
52
  selected_model_name = st.selectbox(
53
  "Select Model",
54
  options=list(model_options.keys()),
55
  index=0
56
  )
 
57
  st.session_state.selected_model = model_options[selected_model_name]
58
+
59
  # Ollama URL input
60
  st.session_state.ngrok_url = st.text_input(
61
  "Ollama Server URL",
62
  value=st.session_state.get("ngrok_url", "http://localhost:11434"),
63
  help="Enter the URL to your Ollama server"
64
  )
65
+
66
  # Conversation history
67
  st.subheader("Conversation History")
68
  if st.button("Clear History"):
69
  st.session_state.messages = []
70
  st.success("History cleared!")
71
+
72
  # Debug info
73
  with st.sidebar.expander("🔧 Debug Info"):
74
+ st.write(f"**OLLAMA_HOST**: {st.session_state.ngrok_url}")
75
+ st.write(f"**Selected Model**: {st.session_state.selected_model}")
76
+ st.write(f"Fallback Mode: {'✅ On' if config.use_fallback else '❌ Off'}")
77
+ st.write(f"Redis Status: {'✅ Healthy' if check_redis_health() else '⚠️ Unavailable'}")
78
+ st.write(f"Env Detected As: {'☁️ HF Space' if config.is_hf_space else '🏠 Local'}")
79
+ st.write(f"HF Token Set: {'✅ Yes' if config.hf_token else '❌ No'}")
80
+
81
  if st.session_state.last_error:
82
  st.warning(f"Last Error: {st.session_state.last_error}")
83
+
84
+ # Ollama API Call Tracking
85
+ if st.session_state.last_ollama_call_success is not None:
86
+ status_icon = "✅ Success" if st.session_state.last_ollama_call_success else "❌ Failed"
87
+ st.write(f"Last Ollama Call: {status_icon}")
88
+ st.write(f"At: {st.session_state.last_ollama_call_time}")
89
+ if st.session_state.last_ollama_response_preview:
90
+ st.code(st.session_state.last_ollama_response_preview[:200] + ("..." if len(st.session_state.last_ollama_response_preview) > 200 else ""), language="text")
91
+
92
+ # Hugging Face API Call Tracking
93
+ if st.session_state.last_hf_call_success is not None:
94
+ status_icon = "✅ Success" if st.session_state.last_hf_call_success else "❌ Failed"
95
+ st.write(f"Last HF Call: {status_icon}")
96
+ st.write(f"At: {st.session_state.last_hf_call_time}")
97
+ if st.session_state.last_hf_response_preview:
98
+ st.code(st.session_state.last_hf_response_preview[:200] + ("..." if len(st.session_state.last_hf_response_preview) > 200 else ""), language="text")
99
+
100
+ # Manual Refresh Button
101
+ if st.button("🔄 Refresh Ollama Status"):
102
+ from services.ollama_monitor import check_ollama_status
103
+ status = check_ollama_status()
104
+ # Fix for Streamlit version - replace st.toast with compatible function
105
+ status_text = f"Ollama Status: {'Running' if status['running'] else 'Unavailable'}"
106
+ st.sidebar.info(status_text)
107
 
108
  # Main chat interface
109
  st.title("🧠 AI Life Coach")
 
123
  placeholder="Type your message here...",
124
  label_visibility="collapsed"
125
  )
 
126
  with col2:
127
  send_button = st.button("Send", key="send_message_button", use_container_width=True)
128
 
 
130
  # Display user message
131
  with st.chat_message("user"):
132
  st.markdown(user_input)
133
+
134
  # Add user message to history
135
  st.session_state.messages.append({"role": "user", "content": user_input})
136
+
137
  # Reset error state
138
  st.session_state.last_error = ""
139
+
140
  # Get conversation history
141
  user_session = session_manager.get_session("default_user")
142
  conversation = user_session.get("conversation", [])
143
  conversation_history = conversation[-5:] # Last 5 messages
144
  conversation_history.append({"role": "user", "content": user_input})
145
+
146
  # Send to backend
147
  with st.chat_message("assistant"):
148
  with st.spinner("AI Coach is thinking..."):
149
  ai_response = None
150
  backend_used = ""
151
  error_msg = ""
152
+
153
  # Try Ollama first if not falling back
154
  if not config.use_fallback:
155
  try:
156
  ai_response = send_to_ollama(
157
+ user_input, conversation_history,
158
+ st.session_state.ngrok_url, st.session_state.selected_model
 
 
159
  )
160
  backend_used = "Ollama"
 
161
  # Capture success metadata
162
  st.session_state.last_ollama_call_success = True
163
  st.session_state.last_ollama_call_time = str(datetime.utcnow())
 
168
  st.session_state.last_ollama_call_success = False
169
  st.session_state.last_ollama_call_time = str(datetime.utcnow())
170
  st.session_state.last_ollama_response_preview = str(e)[:200]
171
+
172
+ # Fallback to Hugging Face if not ai_response and config.hf_token
173
  if not ai_response and config.hf_token:
174
  try:
175
  ai_response = send_to_hf(user_input, conversation_history)
176
  backend_used = "Hugging Face"
 
177
  # Capture success metadata
178
  st.session_state.last_hf_call_success = True
179
  st.session_state.last_hf_call_time = str(datetime.utcnow())
 
184
  st.session_state.last_hf_call_success = False
185
  st.session_state.last_hf_call_time = str(datetime.utcnow())
186
  st.session_state.last_hf_response_preview = str(e)[:200]
187
+
188
  if ai_response:
189
  st.markdown(f"{ai_response}")
 
190
  # Update conversation history
191
  conversation.append({"role": "user", "content": user_input})
192
  conversation.append({"role": "assistant", "content": ai_response})
 
193
  # Update session using the correct method
194
  user_session["conversation"] = conversation
195
  session_manager.update_session("default_user", user_session)
 
196
  # Add assistant response to history
197
  st.session_state.messages.append({"role": "assistant", "content": ai_response})
198
  else:
199
  st.error("Failed to get response from both providers.")
200
  st.session_state.last_error = error_msg or "No response from either provider"
201
+
202
  # Clear input by forcing rerun
203
  st.experimental_rerun()
core/redis_client.py CHANGED
@@ -24,91 +24,44 @@ class RedisClient:
24
  self._connect()
25
 
26
  def _connect(self):
27
- """Establish Redis connection with proper error handling"""
28
  logger.info(f"Attempting Redis connection with:")
29
  logger.info(f" Host: {config.redis_host}")
30
  logger.info(f" Port: {config.redis_port}")
31
  logger.info(f" Username: {'SET' if config.redis_username else 'NOT SET'}")
32
  logger.info(f" Password: {'SET' if config.redis_password else 'NOT SET'}")
33
- logger.info(f" Disable SSL: {config.redis_disable_ssl}")
34
 
35
  if not config.redis_host or config.redis_host == "localhost":
36
  logger.info("Redis not configured, skipping connection")
37
  return None
38
 
39
- # If SSL is explicitly disabled, try non-SSL only
40
- if config.redis_disable_ssl:
41
- try:
42
- host, port = self._parse_host_port(config.redis_host, config.redis_port)
43
- logger.info(f"Connecting to Redis at {host}:{port} (SSL disabled)")
44
-
45
- self._redis_client = redis.Redis(
46
- host=host,
47
- port=port,
48
- username=config.redis_username or None,
49
- password=config.redis_password or None,
50
- decode_responses=True,
51
- socket_connect_timeout=5,
52
- socket_timeout=5,
53
- retry_on_timeout=True,
54
- health_check_interval=30
55
- )
56
-
57
- self._redis_client.ping()
58
- logger.info("Successfully connected to Redis without SSL")
59
- return
60
- except Exception as e:
61
- logger.error(f"Non-SSL connection failed: {e}")
62
- self._redis_client = None
63
- return
64
-
65
- # Try SSL connection first (default for Redis Cloud)
66
  try:
67
  host, port = self._parse_host_port(config.redis_host, config.redis_port)
68
- logger.info(f"Connecting to Redis at {host}:{port} with SSL")
69
 
 
70
  self._redis_client = redis.Redis(
71
  host=host,
72
  port=port,
73
- username=config.redis_username or None,
74
- password=config.redis_password or None,
75
  decode_responses=True,
76
- socket_connect_timeout=5,
77
- socket_timeout=5,
78
  ssl=True,
79
- ssl_cert_reqs=None, # Skip cert verification for Redis Cloud
80
- retry_on_timeout=True,
81
- health_check_interval=30
82
  )
83
 
 
84
  self._redis_client.ping()
85
- logger.info("Successfully connected to Redis with SSL")
86
  return
87
 
88
  except Exception as e:
89
- logger.warning(f"SSL connection failed: {e}, trying without SSL")
90
- try:
91
- host, port = self._parse_host_port(config.redis_host, config.redis_port)
92
-
93
- self._redis_client = redis.Redis(
94
- host=host,
95
- port=port,
96
- username=config.redis_username or None,
97
- password=config.redis_password or None,
98
- decode_responses=True,
99
- socket_connect_timeout=5,
100
- socket_timeout=5,
101
- retry_on_timeout=True,
102
- health_check_interval=30
103
- )
104
-
105
- self._redis_client.ping()
106
- logger.info("Successfully connected to Redis without SSL")
107
- return
108
-
109
- except Exception as e2:
110
- logger.error(f"Could not connect to Redis: {e2}")
111
- self._redis_client = None
112
 
113
  def _parse_host_port(self, host_string: str, default_port: int) -> tuple:
114
  """Parse host and port from host string"""
 
24
  self._connect()
25
 
26
  def _connect(self):
27
+ """Establish Redis connection with proper error handling for Redis Cloud"""
28
  logger.info(f"Attempting Redis connection with:")
29
  logger.info(f" Host: {config.redis_host}")
30
  logger.info(f" Port: {config.redis_port}")
31
  logger.info(f" Username: {'SET' if config.redis_username else 'NOT SET'}")
32
  logger.info(f" Password: {'SET' if config.redis_password else 'NOT SET'}")
 
33
 
34
  if not config.redis_host or config.redis_host == "localhost":
35
  logger.info("Redis not configured, skipping connection")
36
  return None
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  try:
39
  host, port = self._parse_host_port(config.redis_host, config.redis_port)
40
+ logger.info(f"Connecting to Redis Cloud at {host}:{port} with SSL")
41
 
42
+ # Redis Cloud specific connection settings
43
  self._redis_client = redis.Redis(
44
  host=host,
45
  port=port,
46
+ username=config.redis_username if config.redis_username else "default",
47
+ password=config.redis_password,
48
  decode_responses=True,
49
+ socket_connect_timeout=10,
50
+ socket_timeout=10,
51
  ssl=True,
52
+ ssl_cert_reqs=None, # Important for Redis Cloud
53
+ health_check_interval=30,
54
+ retry_on_timeout=True
55
  )
56
 
57
+ # Test connection
58
  self._redis_client.ping()
59
+ logger.info("Successfully connected to Redis Cloud with SSL")
60
  return
61
 
62
  except Exception as e:
63
+ logger.error(f"Redis Cloud SSL connection failed: {e}")
64
+ self._redis_client = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  def _parse_host_port(self, host_string: str, default_port: int) -> tuple:
67
  """Parse host and port from host string"""
requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- streamlit==1.24.0
2
  fastapi==0.95.0
3
  uvicorn==0.21.1
4
  redis==5.0.3
 
1
+ streamlit>=1.28.0
2
  fastapi==0.95.0
3
  uvicorn==0.21.1
4
  redis==5.0.3