rdune71 commited on
Commit
8b21538
·
1 Parent(s): 9cf1bcf

Add ngrok URL input in Streamlit UI and improve diagnostic script

Browse files
Files changed (2) hide show
  1. app.py +181 -82
  2. diagnose_ollama.py +17 -8
app.py CHANGED
@@ -1,22 +1,35 @@
1
- # Force redeploy trigger - version 1.2
2
  import streamlit as st
3
  from utils.config import config
4
  import requests
5
  import json
6
  import os
7
  from core.memory import load_user_state
 
8
 
9
  # Set page config
10
  st.set_page_config(page_title="AI Life Coach", page_icon="🧘", layout="centered")
11
 
 
 
 
 
12
  # Sidebar for user selection
13
  st.sidebar.title("🧘 AI Life Coach")
14
  user = st.sidebar.selectbox("Select User", ["Rob", "Sarah"])
 
 
 
 
 
 
 
 
 
 
15
  st.sidebar.markdown("---")
16
 
17
- # Get the base URL for API calls (works in Hugging Face Spaces)
18
- # In HF Spaces, we need to use the same port for both frontend and backend
19
- # or properly configure the backend service
20
  BASE_URL = os.environ.get("SPACE_ID", "") # Will be set in HF Spaces
21
  IS_HF_SPACE = bool(BASE_URL)
22
 
@@ -26,38 +39,74 @@ NGROK_HEADERS = {
26
  "User-Agent": "AI-Life-Coach-App"
27
  }
28
 
 
 
 
 
 
 
 
29
  # Fetch Ollama status
30
- def get_ollama_status():
31
  try:
32
  # Try to connect to the remote Ollama service directly
33
  response = requests.get(
34
- f"{config.ollama_host}/api/tags",
35
  headers=NGROK_HEADERS,
36
  timeout=10
37
  )
38
  if response.status_code == 200:
39
  models = response.json().get("models", [])
 
 
 
40
  if models:
41
  return {
42
  "running": True,
43
  "model_loaded": models[0].get("name"),
44
- "remote_host": config.ollama_host
 
 
 
 
 
 
 
 
 
45
  }
46
  except Exception as e:
47
- # If direct connection fails, show error
 
48
  return {
49
  "running": False,
50
  "model_loaded": None,
51
  "error": str(e),
52
- "remote_host": config.ollama_host
53
  }
54
-
55
- # If we get here, connection worked but no models
56
- return {
57
- "running": False,
58
- "model_loaded": None,
59
- "remote_host": config.ollama_host
60
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
  # After user selects name, load conversation history
63
  def get_conversation_history(user_id):
@@ -66,18 +115,35 @@ def get_conversation_history(user_id):
66
  return json.loads(user_state["conversation"])
67
  return []
68
 
69
- # Check Ollama status
70
- ollama_status = get_ollama_status()
 
 
 
71
 
72
  # Display Ollama status
73
- if ollama_status["running"]:
74
- st.sidebar.success(f"🧠 Model Running: {ollama_status['model_loaded']}")
75
- st.sidebar.info(f"Connected to: {ollama_status['remote_host']}")
76
- else:
77
- st.sidebar.error("🧠 Ollama is not accessible")
78
- st.sidebar.info(f"Configured host: {ollama_status['remote_host']}")
79
  if "error" in ollama_status:
80
- st.sidebar.caption(f"Error: {ollama_status['error']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
 
82
  # Main chat interface
83
  st.title("🧘 AI Life Coach")
@@ -86,66 +152,99 @@ st.markdown("Talk to your personal development assistant.")
86
  # Show detailed status
87
  with st.expander("🔍 Connection Status"):
88
  st.write("Ollama Status:", ollama_status)
 
 
89
  st.write("Environment Info:")
90
  st.write("- Is HF Space:", IS_HF_SPACE)
91
  st.write("- Base URL:", BASE_URL or "Not in HF Space")
92
  st.write("- Configured Ollama Host:", config.ollama_host)
 
 
93
 
94
- if not ollama_status["running"]:
95
- st.warning("⚠️ Ollama is not accessible. Please check your Ollama/ngrok setup.")
96
- st.info("""
97
- Troubleshooting tips:
98
- 1. Ensure your Ollama service is running locally
99
- 2. Verify your ngrok tunnel is active and pointing to Ollama (port 11434)
100
- 3. Check that the ngrok URL in your .env file matches your active tunnel
101
- 4. Confirm that your ngrok account allows connections from Hugging Face Spaces
102
- """)
103
- else:
104
- # Display conversation history
105
- conversation = get_conversation_history(user)
106
- for msg in conversation:
107
- role = msg["role"].capitalize()
108
- content = msg["content"]
109
- st.markdown(f"**{role}:** {content}")
110
-
111
- # Chat input
112
- user_input = st.text_input("Your message...", key="input")
113
- if st.button("Send"):
114
- if user_input.strip() == "":
115
- st.warning("Please enter a message.")
116
  else:
117
- # Display user message
118
- st.markdown(f"**You:** {user_input}")
119
-
120
- # Send to Ollama directly (bypassing backend for simplicity)
121
- with st.spinner("AI Coach is thinking..."):
122
- try:
123
- # Prepare the prompt with conversation history
124
- conversation_history = [{"role": msg["role"], "content": msg["content"]}
125
- for msg in conversation[-5:]] # Last 5 messages
126
- conversation_history.append({"role": "user", "content": user_input})
127
-
128
- payload = {
129
- "model": config.local_model_name,
130
- "messages": conversation_history,
131
- "stream": False
132
- }
133
-
134
- response = requests.post(
135
- f"{config.ollama_host}/api/chat",
136
- json=payload,
137
- headers=NGROK_HEADERS,
138
- timeout=60
139
- )
140
-
141
- if response.status_code == 200:
142
- response_data = response.json()
143
- ai_response = response_data.get("message", {}).get("content", "")
144
- st.markdown(f"**AI Coach:** {ai_response}")
145
-
146
- # Note: In a production app, we'd save the conversation to Redis here
147
- else:
148
- st.error(f"Failed to get response from Ollama: {response.status_code}")
149
- st.error(response.text[:200])
150
- except Exception as e:
151
- st.error(f"Connection error: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Force redeploy trigger - version 1.5
2
  import streamlit as st
3
  from utils.config import config
4
  import requests
5
  import json
6
  import os
7
  from core.memory import load_user_state
8
+ from core.llm import LLMClient
9
 
10
  # Set page config
11
  st.set_page_config(page_title="AI Life Coach", page_icon="🧘", layout="centered")
12
 
13
+ # Initialize session state for ngrok URL
14
+ if "ngrok_url" not in st.session_state:
15
+ st.session_state.ngrok_url = config.ollama_host
16
+
17
  # Sidebar for user selection
18
  st.sidebar.title("🧘 AI Life Coach")
19
  user = st.sidebar.selectbox("Select User", ["Rob", "Sarah"])
20
+
21
+ # Ngrok URL input in sidebar
22
+ st.sidebar.markdown("---")
23
+ st.sidebar.subheader("Ollama Connection")
24
+ ngrok_input = st.sidebar.text_input("Ngrok URL", value=st.session_state.ngrok_url)
25
+ if st.sidebar.button("Update Ngrok URL"):
26
+ st.session_state.ngrok_url = ngrok_input
27
+ st.sidebar.success("Ngrok URL updated!")
28
+ st.experimental_rerun()
29
+
30
  st.sidebar.markdown("---")
31
 
32
+ # Get environment info
 
 
33
  BASE_URL = os.environ.get("SPACE_ID", "") # Will be set in HF Spaces
34
  IS_HF_SPACE = bool(BASE_URL)
35
 
 
39
  "User-Agent": "AI-Life-Coach-App"
40
  }
41
 
42
+ # Session state for model status
43
+ if "model_status" not in st.session_state:
44
+ st.session_state.model_status = "checking"
45
+
46
+ if "available_models" not in st.session_state:
47
+ st.session_state.available_models = []
48
+
49
  # Fetch Ollama status
50
+ def get_ollama_status(ngrok_url):
51
  try:
52
  # Try to connect to the remote Ollama service directly
53
  response = requests.get(
54
+ f"{ngrok_url}/api/tags",
55
  headers=NGROK_HEADERS,
56
  timeout=10
57
  )
58
  if response.status_code == 200:
59
  models = response.json().get("models", [])
60
+ model_names = [m.get("name") for m in models]
61
+ st.session_state.available_models = model_names
62
+
63
  if models:
64
  return {
65
  "running": True,
66
  "model_loaded": models[0].get("name"),
67
+ "remote_host": ngrok_url,
68
+ "available_models": model_names
69
+ }
70
+ else:
71
+ st.session_state.model_status = "no_models"
72
+ return {
73
+ "running": False,
74
+ "model_loaded": None,
75
+ "remote_host": ngrok_url,
76
+ "message": "Connected to Ollama but no models found"
77
  }
78
  except Exception as e:
79
+ st.session_state.model_status = "unreachable"
80
+ # If direct connection fails, return error info
81
  return {
82
  "running": False,
83
  "model_loaded": None,
84
  "error": str(e),
85
+ "remote_host": ngrok_url
86
  }
87
+
88
+ # Poll for model availability
89
+ def poll_model_status(ngrok_url):
90
+ if st.session_state.model_status in ["checking", "no_models"]:
91
+ try:
92
+ response = requests.get(
93
+ f"{ngrok_url}/api/tags",
94
+ headers=NGROK_HEADERS,
95
+ timeout=5
96
+ )
97
+ if response.status_code == 200:
98
+ models = response.json().get("models", [])
99
+ model_names = [m.get("name") for m in models]
100
+ st.session_state.available_models = model_names
101
+
102
+ if config.local_model_name in model_names:
103
+ st.session_state.model_status = "ready"
104
+ elif models:
105
+ st.session_state.model_status = "different_models"
106
+ else:
107
+ st.session_state.model_status = "no_models"
108
+ except:
109
+ st.session_state.model_status = "unreachable"
110
 
111
  # After user selects name, load conversation history
112
  def get_conversation_history(user_id):
 
115
  return json.loads(user_state["conversation"])
116
  return []
117
 
118
+ # Check Ollama status with the current ngrok URL
119
+ ollama_status = get_ollama_status(st.session_state.ngrok_url)
120
+
121
+ # Poll for model status (run once per session)
122
+ poll_model_status(st.session_state.ngrok_url)
123
 
124
  # Display Ollama status
125
+ use_fallback = not ollama_status.get("running", False) or config.use_fallback
126
+
127
+ if use_fallback:
128
+ st.sidebar.warning("🌐 Using Hugging Face fallback (Ollama not available)")
 
 
129
  if "error" in ollama_status:
130
+ st.sidebar.caption(f"Error: {ollama_status['error'][:50]}...")
131
+ else:
132
+ st.sidebar.success(f"🧠 Ollama Model: {ollama_status['model_loaded']}")
133
+ st.sidebar.info(f"Connected to: {ollama_status['remote_host']}")
134
+
135
+ # Model status indicator
136
+ model_status_container = st.sidebar.empty()
137
+ if st.session_state.model_status == "ready":
138
+ model_status_container.success("✅ Model Ready")
139
+ elif st.session_state.model_status == "checking":
140
+ model_status_container.info("🔍 Checking model...")
141
+ elif st.session_state.model_status == "no_models":
142
+ model_status_container.warning("⚠️ No models found")
143
+ elif st.session_state.model_status == "different_models":
144
+ model_status_container.warning("⚠️ Different models available")
145
+ else: # unreachable
146
+ model_status_container.error("❌ Ollama unreachable")
147
 
148
  # Main chat interface
149
  st.title("🧘 AI Life Coach")
 
152
  # Show detailed status
153
  with st.expander("🔍 Connection Status"):
154
  st.write("Ollama Status:", ollama_status)
155
+ st.write("Model Status:", st.session_state.model_status)
156
+ st.write("Available Models:", st.session_state.available_models)
157
  st.write("Environment Info:")
158
  st.write("- Is HF Space:", IS_HF_SPACE)
159
  st.write("- Base URL:", BASE_URL or "Not in HF Space")
160
  st.write("- Configured Ollama Host:", config.ollama_host)
161
+ st.write("- Current Ngrok URL:", st.session_state.ngrok_url)
162
+ st.write("- Using Fallback:", use_fallback)
163
 
164
+ # Function to send message to Ollama
165
+ def send_to_ollama(user_input, conversation_history, ngrok_url):
166
+ try:
167
+ payload = {
168
+ "model": config.local_model_name,
169
+ "messages": conversation_history,
170
+ "stream": False
171
+ }
172
+
173
+ response = requests.post(
174
+ f"{ngrok_url}/api/chat",
175
+ json=payload,
176
+ headers=NGROK_HEADERS,
177
+ timeout=60
178
+ )
179
+
180
+ if response.status_code == 200:
181
+ response_data = response.json()
182
+ return response_data.get("message", {}).get("content", "")
 
 
 
183
  else:
184
+ st.error(f"Ollama API error: {response.status_code}")
185
+ st.error(response.text[:200])
186
+ return None
187
+ except Exception as e:
188
+ st.error(f"Connection error: {e}")
189
+ return None
190
+
191
+ # Function to send message to Hugging Face (fallback)
192
+ def send_to_hf(user_input, conversation_history):
193
+ try:
194
+ # Initialize LLM client for Hugging Face
195
+ llm_client = LLMClient(provider="huggingface")
196
+
197
+ # Format prompt for HF
198
+ prompt = ""
199
+ for msg in conversation_history:
200
+ role = msg["role"]
201
+ content = msg["content"]
202
+ if role == "system":
203
+ prompt += f"System: {content}\n"
204
+ elif role == "user":
205
+ prompt += f"Human: {content}\n"
206
+ elif role == "assistant":
207
+ prompt += f"Assistant: {content}\n"
208
+ prompt += "Assistant:"
209
+
210
+ response = llm_client.generate(prompt, max_tokens=500, stream=False)
211
+ return response
212
+ except Exception as e:
213
+ st.error(f"Hugging Face API error: {e}")
214
+ return None
215
+
216
+ # Display conversation history
217
+ conversation = get_conversation_history(user)
218
+ for msg in conversation:
219
+ role = msg["role"].capitalize()
220
+ content = msg["content"]
221
+ st.markdown(f"**{role}:** {content}")
222
+
223
+ # Chat input
224
+ user_input = st.text_input("Your message...", key="input")
225
+ if st.button("Send"):
226
+ if user_input.strip() == "":
227
+ st.warning("Please enter a message.")
228
+ else:
229
+ # Display user message
230
+ st.markdown(f"**You:** {user_input}")
231
+
232
+ # Prepare conversation history
233
+ conversation_history = [{"role": msg["role"], "content": msg["content"]}
234
+ for msg in conversation[-5:]] # Last 5 messages
235
+ conversation_history.append({"role": "user", "content": user_input})
236
+
237
+ # Send to appropriate backend
238
+ with st.spinner("AI Coach is thinking..."):
239
+ if use_fallback:
240
+ ai_response = send_to_hf(user_input, conversation_history)
241
+ backend_used = "Hugging Face"
242
+ else:
243
+ ai_response = send_to_ollama(user_input, conversation_history, st.session_state.ngrok_url)
244
+ backend_used = "Ollama"
245
+
246
+ if ai_response:
247
+ st.markdown(f"**AI Coach ({backend_used}):** {ai_response}")
248
+ # Note: In a production app, we'd save the conversation to Redis here
249
+ else:
250
+ st.error(f"Failed to get response from {backend_used}.")
diagnose_ollama.py CHANGED
@@ -1,16 +1,18 @@
1
  #!/usr/bin/env python3
2
  """
3
- Diagnostic script to test Ollama connectivity and model generation
4
  """
5
 
6
  import requests
7
  from utils.config import config
8
 
9
- def test_ollama_connectivity():
10
  """Test if Ollama is reachable from the current environment"""
11
 
 
 
12
  print("=== Ollama Connectivity Diagnostic ===")
13
- print(f"Configured Ollama Host: {config.ollama_host}")
14
  print(f"Configured Model: {config.local_model_name}")
15
  print()
16
 
@@ -24,7 +26,7 @@ def test_ollama_connectivity():
24
  print("Test 1: Checking Ollama host connectivity...")
25
  try:
26
  response = requests.get(
27
- f"{config.ollama_host}/api/tags",
28
  headers=headers,
29
  timeout=10
30
  )
@@ -73,7 +75,7 @@ def test_ollama_connectivity():
73
  try:
74
  # First verify we can connect
75
  response = requests.get(
76
- f"{config.ollama_host}/api/tags",
77
  headers=headers,
78
  timeout=10
79
  )
@@ -94,7 +96,7 @@ def test_ollama_connectivity():
94
  }
95
 
96
  generate_response = requests.post(
97
- f"{config.ollama_host}/api/generate",
98
  json=generate_payload,
99
  headers=headers,
100
  timeout=30
@@ -127,7 +129,7 @@ def test_ollama_connectivity():
127
 
128
  # Test 3: Check localhost as fallback
129
  print("Test 3: Checking localhost fallback (if different from configured host)...")
130
- if config.ollama_host != "http://localhost:11434":
131
  try:
132
  local_response = requests.get(
133
  "http://localhost:11434/api/tags",
@@ -160,4 +162,11 @@ def test_ollama_connectivity():
160
  print("4. If timeout issues, check firewall settings and network connectivity")
161
 
162
  if __name__ == "__main__":
163
- test_ollama_connectivity()
 
 
 
 
 
 
 
 
1
  #!/usr/bin/env python3
2
  """
3
+ Diagnostic script to test Ollama connectivity
4
  """
5
 
6
  import requests
7
  from utils.config import config
8
 
9
+ def test_ollama_connectivity(custom_ngrok_url=None):
10
  """Test if Ollama is reachable from the current environment"""
11
 
12
+ test_url = custom_ngrok_url if custom_ngrok_url else config.ollama_host
13
+
14
  print("=== Ollama Connectivity Diagnostic ===")
15
+ print(f"Testing Ollama Host: {test_url}")
16
  print(f"Configured Model: {config.local_model_name}")
17
  print()
18
 
 
26
  print("Test 1: Checking Ollama host connectivity...")
27
  try:
28
  response = requests.get(
29
+ f"{test_url}/api/tags",
30
  headers=headers,
31
  timeout=10
32
  )
 
75
  try:
76
  # First verify we can connect
77
  response = requests.get(
78
+ f"{test_url}/api/tags",
79
  headers=headers,
80
  timeout=10
81
  )
 
96
  }
97
 
98
  generate_response = requests.post(
99
+ f"{test_url}/api/generate",
100
  json=generate_payload,
101
  headers=headers,
102
  timeout=30
 
129
 
130
  # Test 3: Check localhost as fallback
131
  print("Test 3: Checking localhost fallback (if different from configured host)...")
132
+ if test_url != "http://localhost:11434":
133
  try:
134
  local_response = requests.get(
135
  "http://localhost:11434/api/tags",
 
162
  print("4. If timeout issues, check firewall settings and network connectivity")
163
 
164
  if __name__ == "__main__":
165
+ # Check if user provided a custom ngrok URL
166
+ import sys
167
+ custom_url = None
168
+ if len(sys.argv) > 1:
169
+ custom_url = sys.argv[1]
170
+ print(f"Using custom ngrok URL: {custom_url}")
171
+
172
+ test_ollama_connectivity(custom_url)