Clean up old Redis configuration references and simplify config parsing
Browse files- README.md +28 -28
- utils/config.py +5 -18
- utils/config_validator.py +9 -20
README.md
CHANGED
|
@@ -91,22 +91,24 @@ Configure with OPENAI_API_KEY environment variable.
|
|
| 91 |
### For Local Development (Windows/Ollama):
|
| 92 |
|
| 93 |
1. Install Ollama:
|
| 94 |
-
bash
|
| 95 |
# Download from https://ollama.com/download/OllamaSetup.exe
|
| 96 |
-
|
| 97 |
Pull and run models:
|
|
|
|
|
|
|
| 98 |
ollama pull mistral
|
| 99 |
ollama pull llama3
|
| 100 |
ollama serve
|
| 101 |
-
|
| 102 |
Start ngrok tunnel:
|
| 103 |
-
ngrok http 11434
|
| 104 |
|
|
|
|
|
|
|
| 105 |
Update environment variables:
|
|
|
|
|
|
|
| 106 |
OLLAMA_HOST=https://your-ngrok-url.ngrok-free.app
|
| 107 |
LOCAL_MODEL_NAME=mistral
|
| 108 |
USE_FALLBACK=false
|
| 109 |
-
|
| 110 |
For Production Deployment:
|
| 111 |
|
| 112 |
The application automatically handles provider fallback:
|
|
@@ -117,44 +119,42 @@ Tertiary: OpenAI (if configured)
|
|
| 117 |
Architecture
|
| 118 |
|
| 119 |
This application consists of:
|
| 120 |
-
- Streamlit frontend (app.py)
|
| 121 |
-
- Core LLM abstraction (core/llm.py)
|
| 122 |
-
- Memory management (core/memory.py)
|
| 123 |
-
- Configuration management (utils/config.py)
|
| 124 |
-
- API endpoints (in api/ directory for future expansion)
|
| 125 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
Built with Python, Streamlit, FastAPI, and Redis.
|
| 127 |
|
| 128 |
-
|
| 129 |
-
|
| 130 |
503 Errors with Hugging Face Fallback:
|
| 131 |
-
- Wait 4 minutes for cold start initialization
|
| 132 |
-
- Retry request after endpoint warms up
|
| 133 |
|
|
|
|
|
|
|
| 134 |
Ollama Connection Issues:
|
| 135 |
-
- Verify ollama serve is running locally
|
| 136 |
-
- Check ngrok tunnel status
|
| 137 |
-
- Confirm ngrok URL matches OLLAMA_HOST
|
| 138 |
-
- Test with test_ollama_connection.py
|
| 139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
Redis Connection Problems:
|
| 141 |
-
- The Redis configuration is now hardcoded for maximum reliability
|
| 142 |
-
- If issues persist, check network connectivity to Redis Cloud
|
| 143 |
|
|
|
|
|
|
|
| 144 |
Model Not Found:
|
| 145 |
-
- Pull required model: ollama pull <model-name>
|
| 146 |
-
- Check available models: ollama list
|
| 147 |
|
|
|
|
|
|
|
| 148 |
Diagnostic Scripts:
|
| 149 |
-
- Run python test_ollama_connection.py to verify Ollama connectivity.
|
| 150 |
-
- Run python diagnose_ollama.py for detailed connection diagnostics.
|
| 151 |
-
- Run python test_hardcoded_redis.py to verify Redis connectivity with hardcoded configuration.
|
| 152 |
-
|
| 153 |
-
## New Redis Database Configuration
|
| 154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
The Redis connection now uses the new database credentials:
|
| 156 |
|
| 157 |
-
|
| 158 |
import redis
|
| 159 |
r = redis.Redis(
|
| 160 |
host='redis-16717.c85.us-east-1-2.ec2.redns.redis-cloud.com',
|
|
|
|
| 91 |
### For Local Development (Windows/Ollama):
|
| 92 |
|
| 93 |
1. Install Ollama:
|
| 94 |
+
```bash
|
| 95 |
# Download from https://ollama.com/download/OllamaSetup.exe
|
|
|
|
| 96 |
Pull and run models:
|
| 97 |
+
|
| 98 |
+
|
| 99 |
ollama pull mistral
|
| 100 |
ollama pull llama3
|
| 101 |
ollama serve
|
|
|
|
| 102 |
Start ngrok tunnel:
|
|
|
|
| 103 |
|
| 104 |
+
|
| 105 |
+
ngrok http 11434
|
| 106 |
Update environment variables:
|
| 107 |
+
|
| 108 |
+
|
| 109 |
OLLAMA_HOST=https://your-ngrok-url.ngrok-free.app
|
| 110 |
LOCAL_MODEL_NAME=mistral
|
| 111 |
USE_FALLBACK=false
|
|
|
|
| 112 |
For Production Deployment:
|
| 113 |
|
| 114 |
The application automatically handles provider fallback:
|
|
|
|
| 119 |
Architecture
|
| 120 |
|
| 121 |
This application consists of:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
+
Streamlit frontend (app.py)
|
| 124 |
+
Core LLM abstraction (core/llm.py)
|
| 125 |
+
Memory management (core/memory.py)
|
| 126 |
+
Configuration management (utils/config.py)
|
| 127 |
+
API endpoints (in api/ directory for future expansion)
|
| 128 |
Built with Python, Streamlit, FastAPI, and Redis.
|
| 129 |
|
| 130 |
+
Troubleshooting Common Issues
|
|
|
|
| 131 |
503 Errors with Hugging Face Fallback:
|
|
|
|
|
|
|
| 132 |
|
| 133 |
+
Wait 4 minutes for cold start initialization
|
| 134 |
+
Retry request after endpoint warms up
|
| 135 |
Ollama Connection Issues:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
|
| 137 |
+
Verify ollama serve is running locally
|
| 138 |
+
Check ngrok tunnel status
|
| 139 |
+
Confirm ngrok URL matches OLLAMA_HOST
|
| 140 |
+
Test with test_ollama_connection.py
|
| 141 |
Redis Connection Problems:
|
|
|
|
|
|
|
| 142 |
|
| 143 |
+
The Redis configuration is now hardcoded for maximum reliability
|
| 144 |
+
If issues persist, check network connectivity to Redis Cloud
|
| 145 |
Model Not Found:
|
|
|
|
|
|
|
| 146 |
|
| 147 |
+
Pull required model: ollama pull <model-name>
|
| 148 |
+
Check available models: ollama list
|
| 149 |
Diagnostic Scripts:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
|
| 151 |
+
Run python test_ollama_connection.py to verify Ollama connectivity.
|
| 152 |
+
Run python diagnose_ollama.py for detailed connection diagnostics.
|
| 153 |
+
Run python test_hardcoded_redis.py to verify Redis connectivity with hardcoded configuration.
|
| 154 |
+
New Redis Database Configuration
|
| 155 |
The Redis connection now uses the new database credentials:
|
| 156 |
|
| 157 |
+
|
| 158 |
import redis
|
| 159 |
r = redis.Redis(
|
| 160 |
host='redis-16717.c85.us-east-1-2.ec2.redns.redis-cloud.com',
|
utils/config.py
CHANGED
|
@@ -20,33 +20,22 @@ class Config:
|
|
| 20 |
# Fallback settings
|
| 21 |
self.use_fallback = os.getenv("USE_FALLBACK", "true").lower() == "true"
|
| 22 |
|
| 23 |
-
# Redis configuration (optional for HF)
|
| 24 |
-
self.redis_host = self._sanitize_host(os.getenv("REDIS_HOST", ""))
|
| 25 |
-
self.redis_port = int(os.getenv("REDIS_PORT", "6379"))
|
| 26 |
-
self.redis_username = os.getenv("REDIS_USERNAME", "")
|
| 27 |
-
self.redis_password = os.getenv("REDIS_PASSWORD", "")
|
| 28 |
-
self.redis_retries = int(os.getenv("REDIS_RETRIES", "3"))
|
| 29 |
-
self.redis_retry_delay = int(os.getenv("REDIS_RETRY_DELAY", "1"))
|
| 30 |
-
self.redis_disable_ssl = os.getenv("REDIS_DISABLE_SSL", "false").lower() == "true"
|
| 31 |
-
|
| 32 |
# Local model configuration
|
| 33 |
self.local_model_name = os.getenv("LOCAL_MODEL_NAME", "mistral:latest")
|
| 34 |
self.ollama_host = self._sanitize_url(os.getenv("OLLAMA_HOST", ""))
|
| 35 |
|
| 36 |
# OpenWeather API
|
| 37 |
self.openweather_api_key = os.getenv("OPENWEATHER_API_KEY")
|
| 38 |
-
|
| 39 |
def _sanitize_url(self, url: str) -> str:
|
| 40 |
"""Sanitize URL by removing whitespace and control characters"""
|
| 41 |
if not url:
|
| 42 |
return ""
|
| 43 |
-
|
| 44 |
# Remove leading/trailing whitespace and control characters
|
| 45 |
url = url.strip()
|
| 46 |
-
|
| 47 |
# Remove any newlines, carriage returns, tabs, and null bytes
|
| 48 |
url = re.sub(r'[\r\n\t\0\x0b\x0c]+', '', url)
|
| 49 |
-
|
| 50 |
# Remove any trailing URL encoding artifacts
|
| 51 |
url = url.rstrip('%0a').rstrip('%0d')
|
| 52 |
|
|
@@ -59,20 +48,18 @@ class Config:
|
|
| 59 |
else:
|
| 60 |
# Otherwise default to http
|
| 61 |
url = 'http://' + url
|
| 62 |
-
|
| 63 |
return url
|
| 64 |
-
|
| 65 |
def _sanitize_host(self, host: str) -> str:
|
| 66 |
"""Sanitize host by removing whitespace and control characters"""
|
| 67 |
if not host:
|
| 68 |
return ""
|
| 69 |
-
|
| 70 |
# Remove leading/trailing whitespace and control characters
|
| 71 |
host = host.strip()
|
| 72 |
-
|
| 73 |
# Remove any newlines, carriage returns, tabs, and null bytes
|
| 74 |
host = re.sub(r'[\r\n\t\0\x0b\x0c]+', '', host)
|
| 75 |
-
|
| 76 |
# Remove any trailing URL encoding artifacts
|
| 77 |
host = host.rstrip('%0a').rstrip('%0d')
|
| 78 |
|
|
|
|
| 20 |
# Fallback settings
|
| 21 |
self.use_fallback = os.getenv("USE_FALLBACK", "true").lower() == "true"
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
# Local model configuration
|
| 24 |
self.local_model_name = os.getenv("LOCAL_MODEL_NAME", "mistral:latest")
|
| 25 |
self.ollama_host = self._sanitize_url(os.getenv("OLLAMA_HOST", ""))
|
| 26 |
|
| 27 |
# OpenWeather API
|
| 28 |
self.openweather_api_key = os.getenv("OPENWEATHER_API_KEY")
|
| 29 |
+
|
| 30 |
def _sanitize_url(self, url: str) -> str:
|
| 31 |
"""Sanitize URL by removing whitespace and control characters"""
|
| 32 |
if not url:
|
| 33 |
return ""
|
| 34 |
+
|
| 35 |
# Remove leading/trailing whitespace and control characters
|
| 36 |
url = url.strip()
|
|
|
|
| 37 |
# Remove any newlines, carriage returns, tabs, and null bytes
|
| 38 |
url = re.sub(r'[\r\n\t\0\x0b\x0c]+', '', url)
|
|
|
|
| 39 |
# Remove any trailing URL encoding artifacts
|
| 40 |
url = url.rstrip('%0a').rstrip('%0d')
|
| 41 |
|
|
|
|
| 48 |
else:
|
| 49 |
# Otherwise default to http
|
| 50 |
url = 'http://' + url
|
| 51 |
+
|
| 52 |
return url
|
| 53 |
+
|
| 54 |
def _sanitize_host(self, host: str) -> str:
|
| 55 |
"""Sanitize host by removing whitespace and control characters"""
|
| 56 |
if not host:
|
| 57 |
return ""
|
| 58 |
+
|
| 59 |
# Remove leading/trailing whitespace and control characters
|
| 60 |
host = host.strip()
|
|
|
|
| 61 |
# Remove any newlines, carriage returns, tabs, and null bytes
|
| 62 |
host = re.sub(r'[\r\n\t\0\x0b\x0c]+', '', host)
|
|
|
|
| 63 |
# Remove any trailing URL encoding artifacts
|
| 64 |
host = host.rstrip('%0a').rstrip('%0d')
|
| 65 |
|
utils/config_validator.py
CHANGED
|
@@ -20,8 +20,6 @@ class ConfigValidator:
|
|
| 20 |
# Log current configuration for debugging
|
| 21 |
logger.info(f"Current configuration:")
|
| 22 |
logger.info(f" OLLAMA_HOST: '{config.ollama_host}'")
|
| 23 |
-
logger.info(f" REDIS_HOST: '{config.redis_host}'")
|
| 24 |
-
logger.info(f" REDIS_PORT: {config.redis_port}")
|
| 25 |
|
| 26 |
# Validate Ollama host
|
| 27 |
if config.ollama_host:
|
|
@@ -33,31 +31,23 @@ class ConfigValidator:
|
|
| 33 |
report['valid'] = False
|
| 34 |
else:
|
| 35 |
report['warnings'].append("OLLAMA_HOST not set, local Ollama won't be available")
|
| 36 |
-
|
| 37 |
-
# Validate Redis configuration
|
| 38 |
-
if config.redis_host:
|
| 39 |
-
sanitized_host = config._sanitize_host(config.redis_host)
|
| 40 |
-
if sanitized_host != config.redis_host:
|
| 41 |
-
logger.info(f"Sanitized REDIS_HOST from '{config.redis_host}' to '{sanitized_host}'")
|
| 42 |
-
else:
|
| 43 |
-
report['warnings'].append("Redis not configured, using in-memory storage")
|
| 44 |
-
|
| 45 |
# Validate Hugging Face token
|
| 46 |
if config.hf_token:
|
| 47 |
if len(config.hf_token) < 10: # Basic sanity check
|
| 48 |
report['warnings'].append("HF_TOKEN seems too short to be valid")
|
| 49 |
else:
|
| 50 |
report['warnings'].append("HF_TOKEN not set, Hugging Face models won't be available")
|
| 51 |
-
|
| 52 |
# Validate OpenAI API key
|
| 53 |
if config.openai_api_key:
|
| 54 |
if not re.match(r'^sk-[a-zA-Z0-9]{32,}', config.openai_api_key):
|
| 55 |
report['warnings'].append("OPENAI_API_KEY format looks invalid")
|
| 56 |
else:
|
| 57 |
report['warnings'].append("OPENAI_API_KEY not set, OpenAI models won't be available")
|
| 58 |
-
|
| 59 |
return report
|
| 60 |
-
|
| 61 |
@staticmethod
|
| 62 |
def _is_valid_url(url: str) -> bool:
|
| 63 |
"""Check if URL is valid"""
|
|
@@ -66,13 +56,12 @@ class ConfigValidator:
|
|
| 66 |
return all([result.scheme, result.netloc])
|
| 67 |
except:
|
| 68 |
return False
|
| 69 |
-
|
| 70 |
@staticmethod
|
| 71 |
def _is_valid_host(host: str) -> bool:
|
| 72 |
"""Check if host is valid"""
|
| 73 |
if not host:
|
| 74 |
return False
|
| 75 |
-
|
| 76 |
# Basic regex for hostname validation
|
| 77 |
pattern = r'^[a-zA-Z0-9.-]+$'
|
| 78 |
return bool(re.match(pattern, host))
|
|
@@ -85,13 +74,13 @@ def validate_configuration():
|
|
| 85 |
if report['errors']:
|
| 86 |
logger.error("Configuration validation errors:")
|
| 87 |
for error in report['errors']:
|
| 88 |
-
logger.error(f"
|
| 89 |
-
|
| 90 |
if report['warnings']:
|
| 91 |
logger.warning("Configuration warnings:")
|
| 92 |
for warning in report['warnings']:
|
| 93 |
-
logger.warning(f"
|
| 94 |
-
|
| 95 |
return report['valid']
|
| 96 |
|
| 97 |
# Run validation on import
|
|
|
|
| 20 |
# Log current configuration for debugging
|
| 21 |
logger.info(f"Current configuration:")
|
| 22 |
logger.info(f" OLLAMA_HOST: '{config.ollama_host}'")
|
|
|
|
|
|
|
| 23 |
|
| 24 |
# Validate Ollama host
|
| 25 |
if config.ollama_host:
|
|
|
|
| 31 |
report['valid'] = False
|
| 32 |
else:
|
| 33 |
report['warnings'].append("OLLAMA_HOST not set, local Ollama won't be available")
|
| 34 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
# Validate Hugging Face token
|
| 36 |
if config.hf_token:
|
| 37 |
if len(config.hf_token) < 10: # Basic sanity check
|
| 38 |
report['warnings'].append("HF_TOKEN seems too short to be valid")
|
| 39 |
else:
|
| 40 |
report['warnings'].append("HF_TOKEN not set, Hugging Face models won't be available")
|
| 41 |
+
|
| 42 |
# Validate OpenAI API key
|
| 43 |
if config.openai_api_key:
|
| 44 |
if not re.match(r'^sk-[a-zA-Z0-9]{32,}', config.openai_api_key):
|
| 45 |
report['warnings'].append("OPENAI_API_KEY format looks invalid")
|
| 46 |
else:
|
| 47 |
report['warnings'].append("OPENAI_API_KEY not set, OpenAI models won't be available")
|
| 48 |
+
|
| 49 |
return report
|
| 50 |
+
|
| 51 |
@staticmethod
|
| 52 |
def _is_valid_url(url: str) -> bool:
|
| 53 |
"""Check if URL is valid"""
|
|
|
|
| 56 |
return all([result.scheme, result.netloc])
|
| 57 |
except:
|
| 58 |
return False
|
| 59 |
+
|
| 60 |
@staticmethod
|
| 61 |
def _is_valid_host(host: str) -> bool:
|
| 62 |
"""Check if host is valid"""
|
| 63 |
if not host:
|
| 64 |
return False
|
|
|
|
| 65 |
# Basic regex for hostname validation
|
| 66 |
pattern = r'^[a-zA-Z0-9.-]+$'
|
| 67 |
return bool(re.match(pattern, host))
|
|
|
|
| 74 |
if report['errors']:
|
| 75 |
logger.error("Configuration validation errors:")
|
| 76 |
for error in report['errors']:
|
| 77 |
+
logger.error(f" - {error}")
|
| 78 |
+
|
| 79 |
if report['warnings']:
|
| 80 |
logger.warning("Configuration warnings:")
|
| 81 |
for warning in report['warnings']:
|
| 82 |
+
logger.warning(f" - {warning}")
|
| 83 |
+
|
| 84 |
return report['valid']
|
| 85 |
|
| 86 |
# Run validation on import
|