From ef902e418b093abc05183e2de62f43fdabe8ff1a Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 13:41:12 +0530 Subject: [PATCH 01/11] feat: Add support for Ollama and improve setup stability This commit introduces support for using Ollama as an LLM provider and includes several fixes to improve the stability of the setup process. Key changes: - Added Ollama as a selectable LLM provider in the setup script. - Fixed the backend code to correctly handle the Ollama provider. - Improved the docker-compose setup with healthchecks and named volumes to prevent race conditions and permission issues with MongoDB and Caddy. - Updated the setup script to automatically configure the Ollama URL correctly. --- backends/advanced/docker-compose.yml | 39 ++++++++++++------- backends/advanced/init.py | 4 ++ .../src/advanced_omi_backend/llm_client.py | 8 +++- .../src/advanced_omi_backend/memory/config.py | 25 +++++++++++- .../memory/memory_service.py | 2 +- .../memory/providers/llm_providers.py | 10 +++++ backends/advanced/uv.lock | 2 +- 7 files changed, 71 insertions(+), 19 deletions(-) diff --git a/backends/advanced/docker-compose.yml b/backends/advanced/docker-compose.yml index be26ec4d..86c10c89 100644 --- a/backends/advanced/docker-compose.yml +++ b/backends/advanced/docker-compose.yml @@ -37,7 +37,7 @@ services: qdrant: condition: service_started mongo: - condition: service_started + condition: service_healthy redis: condition: service_healthy # neo4j-mem0: @@ -79,7 +79,7 @@ services: redis: condition: service_healthy mongo: - condition: service_started + condition: service_healthy qdrant: condition: service_started restart: unless-stopped @@ -112,8 +112,8 @@ services: - "80:80" # HTTP redirect to HTTPS volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - - ./data/caddy_data:/data - - ./data/caddy_config:/config + - caddy_data:/data + - caddy_config:/config depends_on: friend-backend: condition: service_healthy @@ -151,7 +151,13 @@ services: ports: - "27017:27017" volumes: - - ./data/mongo_data:/data/db + - mongo_data:/data/db + healthcheck: + test: ["CMD", "mongosh", "--eval", "db.runCommand('ping')"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s redis: image: redis:7-alpine @@ -216,13 +222,16 @@ networks: default: name: friend-network -# Question: These are named volumes, but they are not being used, right? Can we remove them? -# volumes: -# ollama_data: -# driver: local -# mongo_data: -# driver: local -# neo4j_data: -# driver: local -# neo4j_logs: -# driver: local +volumes: + ollama_data: + driver: local + mongo_data: + driver: local + caddy_data: + driver: local + caddy_config: + driver: local + neo4j_data: + driver: local + neo4j_logs: + driver: local diff --git a/backends/advanced/init.py b/backends/advanced/init.py index 4e345ec1..e1f085ea 100644 --- a/backends/advanced/init.py +++ b/backends/advanced/init.py @@ -243,6 +243,10 @@ def setup_llm(self): self.console.print("[blue][INFO][/blue] Ollama selected") base_url = self.prompt_value("Ollama server URL", "http://host.docker.internal:11434") + if not base_url.endswith("/v1"): + base_url = base_url.rstrip("/") + "/v1" + self.console.print(f"[blue][INFO][/blue] Automatically appending /v1 to Ollama URL: {base_url}") + model = self.prompt_value("Ollama model", "llama3.2") self.config["OLLAMA_BASE_URL"] = base_url diff --git a/backends/advanced/src/advanced_omi_backend/llm_client.py b/backends/advanced/src/advanced_omi_backend/llm_client.py index 03c15db0..87d37eb7 100644 --- a/backends/advanced/src/advanced_omi_backend/llm_client.py +++ b/backends/advanced/src/advanced_omi_backend/llm_client.py @@ -135,12 +135,18 @@ def create_client() -> LLMClient: """Create an LLM client based on LLM_PROVIDER environment variable.""" provider = os.getenv("LLM_PROVIDER", "openai").lower() - if provider in ["openai", "ollama"]: + if provider == "openai": return OpenAILLMClient( api_key=os.getenv("OPENAI_API_KEY"), base_url=os.getenv("OPENAI_BASE_URL"), model=os.getenv("OPENAI_MODEL"), ) + elif provider == "ollama": + return OpenAILLMClient( + api_key="dummy", # Ollama doesn't require an API key + base_url=os.getenv("OLLAMA_BASE_URL"), + model=os.getenv("OLLAMA_MODEL"), + ) else: raise ValueError(f"Unsupported LLM provider: {provider}") diff --git a/backends/advanced/src/advanced_omi_backend/memory/config.py b/backends/advanced/src/advanced_omi_backend/memory/config.py index 7b821eab..92b1f11c 100644 --- a/backends/advanced/src/advanced_omi_backend/memory/config.py +++ b/backends/advanced/src/advanced_omi_backend/memory/config.py @@ -12,6 +12,7 @@ class LLMProvider(Enum): """Supported LLM providers.""" OPENAI = "openai" + OLLAMA = "ollama" CUSTOM = "custom" @@ -72,6 +73,7 @@ def create_ollama_config( ) -> Dict[str, Any]: """Create Ollama configuration.""" return { + "api_key": "dummy", # Ollama doesn't require an API key "base_url": base_url, "model": model, "embedding_model": embedding_model, @@ -147,9 +149,13 @@ def build_memory_config_from_env() -> MemoryConfig: # Get LLM provider from environment llm_provider = os.getenv("LLM_PROVIDER", "openai").lower() - if llm_provider not in ["openai"]: + if llm_provider not in ["openai", "ollama"]: raise ValueError(f"Unsupported LLM provider: {llm_provider}") + llm_config = None + llm_provider_enum = None + embedding_dims = 1536 # Default + # Build LLM configuration if llm_provider == "openai": openai_api_key = os.getenv("OPENAI_API_KEY") @@ -182,7 +188,24 @@ def build_memory_config_from_env() -> MemoryConfig: else: # Default for OpenAI embedding models embedding_dims = 1536 + + elif llm_provider == "ollama": + base_url = os.getenv("OLLAMA_BASE_URL") + if not base_url: + raise ValueError("OLLAMA_BASE_URL required for Ollama provider") + model = os.getenv("OLLAMA_MODEL") or "llama2" + embedding_model = "nomic-embed-text" # Hardcoded for now + memory_logger.info(f"🔧 Memory config: LLM={model}, Embedding={embedding_model}, Base URL={base_url}") + + llm_config = create_ollama_config( + base_url=base_url, + model=model, + embedding_model=embedding_model, + ) + llm_provider_enum = LLMProvider.OLLAMA + embedding_dims = 768 # For nomic-embed-text + # Build vector store configuration vector_store_provider = os.getenv("VECTOR_STORE_PROVIDER", "qdrant").lower() diff --git a/backends/advanced/src/advanced_omi_backend/memory/memory_service.py b/backends/advanced/src/advanced_omi_backend/memory/memory_service.py index 46af0a75..6460aa25 100644 --- a/backends/advanced/src/advanced_omi_backend/memory/memory_service.py +++ b/backends/advanced/src/advanced_omi_backend/memory/memory_service.py @@ -69,7 +69,7 @@ async def initialize(self) -> None: try: # Initialize LLM provider - if self.config.llm_provider == LLMProviderEnum.OPENAI: + if self.config.llm_provider in [LLMProviderEnum.OPENAI, LLMProviderEnum.OLLAMA]: self.llm_provider = OpenAIProvider(self.config.llm_config) else: raise ValueError(f"Unsupported LLM provider: {self.config.llm_provider}") diff --git a/backends/advanced/src/advanced_omi_backend/memory/providers/llm_providers.py b/backends/advanced/src/advanced_omi_backend/memory/providers/llm_providers.py index 2d54d3fa..e6520d2b 100644 --- a/backends/advanced/src/advanced_omi_backend/memory/providers/llm_providers.py +++ b/backends/advanced/src/advanced_omi_backend/memory/providers/llm_providers.py @@ -10,6 +10,8 @@ import json import logging +import os +import httpx from typing import Any, Dict, List, Optional # TODO: Re-enable spacy when Docker build is fixed @@ -237,6 +239,14 @@ async def test_connection(self) -> bool: True if connection successful, False otherwise """ try: + # For Ollama, just check if the base URL is reachable + if os.getenv("LLM_PROVIDER", "openai").lower() == "ollama": + import httpx + async with httpx.AsyncClient() as client: + response = await client.get(self.base_url) + response.raise_for_status() + return True + import langfuse.openai as openai client = openai.AsyncOpenAI( diff --git a/backends/advanced/uv.lock b/backends/advanced/uv.lock index 153cf546..cda2801e 100644 --- a/backends/advanced/uv.lock +++ b/backends/advanced/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.12" resolution-markers = [ "python_full_version >= '3.13'", From a671926a7145e5c4cb406643f4bc3ccbcba520cd Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 19:26:45 +0530 Subject: [PATCH 02/11] Fix: Ollama health check in backend services Adjusted Ollama health check logic in llm_client.py and llm_providers.py to correctly interact with Ollama's native and OpenAI-compatible APIs, resolving 'LLM provider connection failed' errors. --- .../src/advanced_omi_backend/llm_client.py | 73 +++++++++++++++---- .../memory/providers/llm_providers.py | 3 +- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/backends/advanced/src/advanced_omi_backend/llm_client.py b/backends/advanced/src/advanced_omi_backend/llm_client.py index 87d37eb7..8d6bf9e9 100644 --- a/backends/advanced/src/advanced_omi_backend/llm_client.py +++ b/backends/advanced/src/advanced_omi_backend/llm_client.py @@ -45,11 +45,13 @@ class OpenAILLMClient(LLMClient): def __init__( self, + provider: str, api_key: str | None = None, base_url: str | None = None, model: str | None = None, temperature: float = 0.1, ): + self.provider = provider super().__init__(model, temperature) self.api_key = api_key or os.getenv("OPENAI_API_KEY") self.base_url = base_url or os.getenv("OPENAI_BASE_URL") @@ -94,25 +96,69 @@ def generate( self.logger.error(f"Error generating completion: {e}") raise - def health_check(self) -> Dict: + async def health_check(self) -> Dict: """Check OpenAI-compatible service health.""" try: - # For OpenAI API, check if we have valid configuration - # Avoid calling /models endpoint as it can be unreliable - if self.api_key and self.api_key != "dummy" and self.model: + if not (self.model and self.base_url): return { - "status": "✅ Connected", + "status": "⚠️ Configuration incomplete (missing model or base_url)", "base_url": self.base_url, "default_model": self.model, "api_key_configured": bool(self.api_key and self.api_key != "dummy"), } + + if self.provider == "ollama": + # For Ollama, attempt to reach the base_url + import aiohttp + try: + async with aiohttp.ClientSession() as session: + # Ollama's health endpoint is usually just the base URL or / + ollama_health_url = self.base_url.replace("/v1", "") if self.base_url.endswith("/v1") else self.base_url + async with session.get(f"{ollama_health_url}/api/version", timeout=aiohttp.ClientTimeout(total=5)) as response: + if response.status == 200: + return { + "status": "✅ Connected", + "base_url": self.base_url, + "default_model": self.model, + "api_key_configured": False, # Ollama doesn't use API keys + } + else: + return { + "status": f"⚠️ Ollama Unhealthy: HTTP {response.status}", + "base_url": self.base_url, + "default_model": self.model, + "api_key_configured": False, + } + except aiohttp.ClientError as e: + return { + "status": "❌ Ollama Connection Failed", + "base_url": self.base_url, + "default_model": self.model, + "api_key_configured": False, + } + except asyncio.TimeoutError: + return { + "status": "❌ Ollama Connection Timeout (5s)", + "base_url": self.base_url, + "default_model": self.model, + "api_key_configured": False, + } else: - return { - "status": "⚠️ Configuration incomplete", - "base_url": self.base_url, - "default_model": self.model, - "api_key_configured": bool(self.api_key and self.api_key != "dummy"), - } + # For other OpenAI-compatible APIs, check configuration + if self.api_key and self.api_key != "dummy": + return { + "status": "✅ Connected", + "base_url": self.base_url, + "default_model": self.model, + "api_key_configured": bool(self.api_key and self.api_key != "dummy"), + } + else: + return { + "status": "⚠️ Configuration incomplete (missing API key)", + "base_url": self.base_url, + "default_model": self.model, + "api_key_configured": bool(self.api_key and self.api_key != "dummy"), + } except Exception as e: self.logger.error(f"Health check failed: {e}") return { @@ -137,12 +183,14 @@ def create_client() -> LLMClient: if provider == "openai": return OpenAILLMClient( + provider="openai", api_key=os.getenv("OPENAI_API_KEY"), base_url=os.getenv("OPENAI_BASE_URL"), model=os.getenv("OPENAI_MODEL"), ) elif provider == "ollama": return OpenAILLMClient( + provider="ollama", api_key="dummy", # Ollama doesn't require an API key base_url=os.getenv("OLLAMA_BASE_URL"), model=os.getenv("OLLAMA_MODEL"), @@ -187,5 +235,4 @@ async def async_generate( async def async_health_check() -> Dict: """Async wrapper for LLM health check.""" client = get_llm_client() - loop = asyncio.get_running_loop() - return await loop.run_in_executor(None, client.health_check) + return await client.health_check() diff --git a/backends/advanced/src/advanced_omi_backend/memory/providers/llm_providers.py b/backends/advanced/src/advanced_omi_backend/memory/providers/llm_providers.py index e6520d2b..b1a5bb0c 100644 --- a/backends/advanced/src/advanced_omi_backend/memory/providers/llm_providers.py +++ b/backends/advanced/src/advanced_omi_backend/memory/providers/llm_providers.py @@ -243,7 +243,8 @@ async def test_connection(self) -> bool: if os.getenv("LLM_PROVIDER", "openai").lower() == "ollama": import httpx async with httpx.AsyncClient() as client: - response = await client.get(self.base_url) + # For Ollama, test connection by hitting the /v1/models endpoint + response = await client.get(f"{self.base_url}/models") response.raise_for_status() return True From cf7cc238afbeb20b56f36b1f12c7818be3ffccf2 Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 19:57:20 +0530 Subject: [PATCH 03/11] Feat: Add OLLAMA_EMBEDDER_MODEL to advanced backend setup Introduced a prompt for OLLAMA_EMBEDDER_MODEL in backends/advanced/init.py, defaulting to 'nomic-embed-text:latest', and included it in the generated .env file. This ensures proper configuration for Ollama embedding models. --- backends/advanced/init.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backends/advanced/init.py b/backends/advanced/init.py index e1f085ea..937d8c52 100644 --- a/backends/advanced/init.py +++ b/backends/advanced/init.py @@ -249,10 +249,15 @@ def setup_llm(self): model = self.prompt_value("Ollama model", "llama3.2") + # Prompt for Ollama embedder model, defaulting to 'nomic-embed-text:latest' + # IMPORTANT: Ensure this model is capable of generating embeddings. + embedder_model = self.prompt_value("Ollama embedder model", "nomic-embed-text:latest") + self.config["OLLAMA_BASE_URL"] = base_url self.config["OLLAMA_MODEL"] = model + self.config["OLLAMA_EMBEDDER_MODEL"] = embedder_model # Add this line self.console.print("[green][SUCCESS][/green] Ollama configured") - self.console.print("[yellow][WARNING][/yellow] Make sure Ollama is running and the model is pulled") + self.console.print("[yellow][WARNING][/yellow] Make sure Ollama is running and all required models (LLM and embedder) are pulled") elif choice == "3": self.console.print("[blue][INFO][/blue] Skipping LLM setup - memory extraction disabled") From 66dc26821e5613393c857acc2fcc045c48861eb1 Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 20:12:39 +0530 Subject: [PATCH 04/11] Feat: Enforce explicit OLLAMA_MODEL and OLLAMA_EMBEDDER_MODEL configuration Removed fallback defaults for OLLAMA_MODEL and OLLAMA_EMBEDDER_MODEL in memory/config.py. These environment variables are now strictly required, and a ValueError will be raised if they are not set. --- .../advanced/src/advanced_omi_backend/memory/config.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backends/advanced/src/advanced_omi_backend/memory/config.py b/backends/advanced/src/advanced_omi_backend/memory/config.py index 92b1f11c..25d02e85 100644 --- a/backends/advanced/src/advanced_omi_backend/memory/config.py +++ b/backends/advanced/src/advanced_omi_backend/memory/config.py @@ -194,8 +194,12 @@ def build_memory_config_from_env() -> MemoryConfig: if not base_url: raise ValueError("OLLAMA_BASE_URL required for Ollama provider") - model = os.getenv("OLLAMA_MODEL") or "llama2" - embedding_model = "nomic-embed-text" # Hardcoded for now + model = os.getenv("OLLAMA_MODEL") + if not model: + raise ValueError("OLLAMA_MODEL required for Ollama provider") + embedding_model = os.getenv("OLLAMA_EMBEDDER_MODEL") + if not embedding_model: + raise ValueError("OLLAMA_EMBEDDER_MODEL required for Ollama provider") memory_logger.info(f"🔧 Memory config: LLM={model}, Embedding={embedding_model}, Base URL={base_url}") llm_config = create_ollama_config( From f0d4c7a295c9629fe7b5f9e0d53fab19fc2ea443 Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 20:56:34 +0530 Subject: [PATCH 05/11] Feat: Display Ollama embedder model status in UI - Backend (llm_client.py, health_routes.py): Extended health check to include Ollama embedder model status and updated overall health logic. - Frontend (System.tsx): Updated UI to display main Ollama model name and embedder model status in a consistent format. --- .../src/advanced_omi_backend/llm_client.py | 66 +++++++++++-------- .../routers/modules/health_routes.py | 15 ++++- backends/advanced/webui/src/pages/System.tsx | 14 +++- 3 files changed, 65 insertions(+), 30 deletions(-) diff --git a/backends/advanced/src/advanced_omi_backend/llm_client.py b/backends/advanced/src/advanced_omi_backend/llm_client.py index 8d6bf9e9..0f71ed97 100644 --- a/backends/advanced/src/advanced_omi_backend/llm_client.py +++ b/backends/advanced/src/advanced_omi_backend/llm_client.py @@ -108,41 +108,51 @@ async def health_check(self) -> Dict: } if self.provider == "ollama": - # For Ollama, attempt to reach the base_url import aiohttp + ollama_health_url = self.base_url.replace("/v1", "") if self.base_url.endswith("/v1") else self.base_url + + # Initialize response with main LLM status + response_data = { + "status": "❌ Unknown", + "base_url": self.base_url, + "default_model": self.model, + "api_key_configured": False, + "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), # Add embedder model info + "embedder_status": "❌ Not Checked" # Default embedder status + } + try: async with aiohttp.ClientSession() as session: - # Ollama's health endpoint is usually just the base URL or / - ollama_health_url = self.base_url.replace("/v1", "") if self.base_url.endswith("/v1") else self.base_url + # Check main Ollama server health async with session.get(f"{ollama_health_url}/api/version", timeout=aiohttp.ClientTimeout(total=5)) as response: if response.status == 200: - return { - "status": "✅ Connected", - "base_url": self.base_url, - "default_model": self.model, - "api_key_configured": False, # Ollama doesn't use API keys - } + response_data["status"] = "✅ Connected" else: - return { - "status": f"⚠️ Ollama Unhealthy: HTTP {response.status}", - "base_url": self.base_url, - "default_model": self.model, - "api_key_configured": False, - } - except aiohttp.ClientError as e: - return { - "status": "❌ Ollama Connection Failed", - "base_url": self.base_url, - "default_model": self.model, - "api_key_configured": False, - } + response_data["status"] = f"⚠️ Ollama Unhealthy: HTTP {response.status}" + + # Check embedder model availability + embedder_model_name = os.getenv("OLLAMA_EMBEDDER_MODEL") + if embedder_model_name: + try: + # Use /api/show to check if model exists + async with session.post(f"{ollama_health_url}/api/show", json={"name": embedder_model_name}, timeout=aiohttp.ClientTimeout(total=5)) as embedder_response: + if embedder_response.status == 200: + response_data["embedder_status"] = "✅ Available" + else: + response_data["embedder_status"] = "⚠️ Embedder Model Unhealthy" + except aiohttp.ClientError: + response_data["embedder_status"] = "❌ Embedder Model Connection Failed" + except asyncio.TimeoutError: + response_data["embedder_status"] = "❌ Embedder Model Timeout" + else: + response_data["embedder_status"] = "⚠️ Embedder Model Not Configured" + + except aiohttp.ClientError: + response_data["status"] = "❌ Ollama Connection Failed" except asyncio.TimeoutError: - return { - "status": "❌ Ollama Connection Timeout (5s)", - "base_url": self.base_url, - "default_model": self.model, - "api_key_configured": False, - } + response_data["status"] = "❌ Ollama Connection Timeout (5s)" + + return response_data else: # For other OpenAI-compatible APIs, check configuration if self.api_key and self.api_key != "dummy": diff --git a/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py b/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py index 4981ca39..b0288771 100644 --- a/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py +++ b/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py @@ -190,12 +190,21 @@ async def health_check(): # Check LLM service (non-critical service - may not be running) try: llm_health = await asyncio.wait_for(async_health_check(), timeout=8.0) + + # Determine overall health for audioai service based on LLM and embedder status + is_llm_healthy = "✅" in llm_health.get("status", "") + is_embedder_healthy = "✅" in llm_health.get("embedder_status", "") or llm_health.get("embedder_status") == "⚠️ Embedder Model Not Configured" # Not configured is not unhealthy + + audioai_overall_healthy = is_llm_healthy and is_embedder_healthy + health_status["services"]["audioai"] = { "status": llm_health.get("status", "❌ Unknown"), - "healthy": "✅" in llm_health.get("status", ""), + "healthy": audioai_overall_healthy, # Updated healthy flag "base_url": llm_health.get("base_url", ""), "model": llm_health.get("default_model", ""), "provider": os.getenv("LLM_PROVIDER", "openai"), + "embedder_model": llm_health.get("embedder_model", ""), # Added + "embedder_status": llm_health.get("embedder_status", ""), # Added "critical": False, } except asyncio.TimeoutError: @@ -204,6 +213,8 @@ async def health_check(): "healthy": False, "provider": os.getenv("LLM_PROVIDER", "openai"), "critical": False, + "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), # Added for context + "embedder_status": "❌ Not Checked (Timeout)" # Added } overall_healthy = False except Exception as e: @@ -212,6 +223,8 @@ async def health_check(): "healthy": False, "provider": os.getenv("LLM_PROVIDER", "openai"), "critical": False, + "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), # Added for context + "embedder_status": "❌ Not Checked (Connection Failed)" # Added } overall_healthy = False diff --git a/backends/advanced/webui/src/pages/System.tsx b/backends/advanced/webui/src/pages/System.tsx index 3ca54a59..0e7f0f44 100644 --- a/backends/advanced/webui/src/pages/System.tsx +++ b/backends/advanced/webui/src/pages/System.tsx @@ -9,6 +9,12 @@ interface HealthData { services: Record timestamp?: string } @@ -273,9 +279,15 @@ export default function System() { )} {(status as any).provider && ( - ({(status as any).provider}) + ({(status as any).provider} + {service === 'audioai' && (status as any).model && ` - ${(status as any).model}`}) )} + {service === 'audioai' && (status as any).embedder_model && ( +
+ Embedder: {(status as any).embedder_status} ({(status as any).embedder_model}) +
+ )} {service === 'redis' && (status as any).worker_count !== undefined && (
Workers: {(status as any).worker_count} total From 56360558ade09b0b7c3983c824521d8b5a93b681 Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 21:07:58 +0530 Subject: [PATCH 06/11] Refactor: Remove unnecessary comments from code Cleaned up various comments like '# Added', '# Added for context', '// New field', etc., to improve code readability and adhere to best practices. --- backends/advanced/init.py | 4 +--- .../src/advanced_omi_backend/llm_client.py | 4 ++-- .../routers/modules/health_routes.py | 14 +++++++------- backends/advanced/webui/src/pages/System.tsx | 10 +++++----- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/backends/advanced/init.py b/backends/advanced/init.py index 937d8c52..cd13cbb4 100644 --- a/backends/advanced/init.py +++ b/backends/advanced/init.py @@ -249,13 +249,11 @@ def setup_llm(self): model = self.prompt_value("Ollama model", "llama3.2") - # Prompt for Ollama embedder model, defaulting to 'nomic-embed-text:latest' - # IMPORTANT: Ensure this model is capable of generating embeddings. embedder_model = self.prompt_value("Ollama embedder model", "nomic-embed-text:latest") self.config["OLLAMA_BASE_URL"] = base_url self.config["OLLAMA_MODEL"] = model - self.config["OLLAMA_EMBEDDER_MODEL"] = embedder_model # Add this line + self.config["OLLAMA_EMBEDDER_MODEL"] = embedder_model self.console.print("[green][SUCCESS][/green] Ollama configured") self.console.print("[yellow][WARNING][/yellow] Make sure Ollama is running and all required models (LLM and embedder) are pulled") diff --git a/backends/advanced/src/advanced_omi_backend/llm_client.py b/backends/advanced/src/advanced_omi_backend/llm_client.py index 0f71ed97..f3b0bb18 100644 --- a/backends/advanced/src/advanced_omi_backend/llm_client.py +++ b/backends/advanced/src/advanced_omi_backend/llm_client.py @@ -117,8 +117,8 @@ async def health_check(self) -> Dict: "base_url": self.base_url, "default_model": self.model, "api_key_configured": False, - "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), # Add embedder model info - "embedder_status": "❌ Not Checked" # Default embedder status + "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), + "embedder_status": "❌ Not Checked" } try: diff --git a/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py b/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py index b0288771..ede25795 100644 --- a/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py +++ b/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py @@ -199,12 +199,12 @@ async def health_check(): health_status["services"]["audioai"] = { "status": llm_health.get("status", "❌ Unknown"), - "healthy": audioai_overall_healthy, # Updated healthy flag + "healthy": audioai_overall_healthy, "base_url": llm_health.get("base_url", ""), "model": llm_health.get("default_model", ""), "provider": os.getenv("LLM_PROVIDER", "openai"), - "embedder_model": llm_health.get("embedder_model", ""), # Added - "embedder_status": llm_health.get("embedder_status", ""), # Added + "embedder_model": llm_health.get("embedder_model", ""), + "embedder_status": llm_health.get("embedder_status", ""), "critical": False, } except asyncio.TimeoutError: @@ -213,8 +213,8 @@ async def health_check(): "healthy": False, "provider": os.getenv("LLM_PROVIDER", "openai"), "critical": False, - "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), # Added for context - "embedder_status": "❌ Not Checked (Timeout)" # Added + "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), + "embedder_status": "❌ Not Checked (Timeout)" } overall_healthy = False except Exception as e: @@ -223,8 +223,8 @@ async def health_check(): "healthy": False, "provider": os.getenv("LLM_PROVIDER", "openai"), "critical": False, - "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), # Added for context - "embedder_status": "❌ Not Checked (Connection Failed)" # Added + "embedder_model": os.getenv("OLLAMA_EMBEDDER_MODEL"), + "embedder_status": "❌ Not Checked (Connection Failed)" } overall_healthy = False diff --git a/backends/advanced/webui/src/pages/System.tsx b/backends/advanced/webui/src/pages/System.tsx index 0e7f0f44..f5996d97 100644 --- a/backends/advanced/webui/src/pages/System.tsx +++ b/backends/advanced/webui/src/pages/System.tsx @@ -9,12 +9,12 @@ interface HealthData { services: Record timestamp?: string } From ddd8a1149929d5fb716b61cbdbc0d1a519cf948d Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 22:34:41 +0530 Subject: [PATCH 07/11] Fix: LLM health check for OpenAI provider Adjusted the health check logic in health_routes.py to correctly determine the 'audioai' service health when the LLM provider is OpenAI. Previously, the embedder status was incorrectly factored into the overall health for OpenAI, leading to an 'unhealthy' status. This change ensures that for OpenAI, the embedder status is considered 'Not Applicable' and does not negatively impact the overall health. --- .../routers/modules/health_routes.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py b/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py index ede25795..49160c13 100644 --- a/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py +++ b/backends/advanced/src/advanced_omi_backend/routers/modules/health_routes.py @@ -193,7 +193,14 @@ async def health_check(): # Determine overall health for audioai service based on LLM and embedder status is_llm_healthy = "✅" in llm_health.get("status", "") - is_embedder_healthy = "✅" in llm_health.get("embedder_status", "") or llm_health.get("embedder_status") == "⚠️ Embedder Model Not Configured" # Not configured is not unhealthy + + # Determine embedder health based on provider + llm_provider = os.getenv("LLM_PROVIDER", "openai").lower() + if llm_provider == "ollama": + is_embedder_healthy = "✅" in llm_health.get("embedder_status", "") or llm_health.get("embedder_status") == "⚠️ Embedder Model Not Configured" + else: + # For OpenAI and other providers, embedder status is not applicable, so consider it healthy + is_embedder_healthy = True audioai_overall_healthy = is_llm_healthy and is_embedder_healthy From de1bc4b97ae2b63e7a101afee7e4542aea824589 Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 19:57:20 +0530 Subject: [PATCH 08/11] Feat: Add OLLAMA_EMBEDDER_MODEL to advanced backend setup Introduced a prompt for OLLAMA_EMBEDDER_MODEL in backends/advanced/init.py, defaulting to 'nomic-embed-text:latest', and included it in the generated .env file. This ensures proper configuration for Ollama embedding models. --- backends/advanced/init.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backends/advanced/init.py b/backends/advanced/init.py index cd13cbb4..f90051c6 100644 --- a/backends/advanced/init.py +++ b/backends/advanced/init.py @@ -249,6 +249,8 @@ def setup_llm(self): model = self.prompt_value("Ollama model", "llama3.2") + # Prompt for Ollama embedder model, defaulting to 'nomic-embed-text:latest' + # IMPORTANT: Ensure this model is capable of generating embeddings. embedder_model = self.prompt_value("Ollama embedder model", "nomic-embed-text:latest") self.config["OLLAMA_BASE_URL"] = base_url From 91e5cee60a49510f6b5a840b5f1d1919ba3ecb67 Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Sat, 18 Oct 2025 21:07:58 +0530 Subject: [PATCH 09/11] Refactor: Remove unnecessary comments from code Cleaned up various comments like '# Added', '# Added for context', '// New field', etc., to improve code readability and adhere to best practices. --- backends/advanced/init.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/backends/advanced/init.py b/backends/advanced/init.py index f90051c6..cd13cbb4 100644 --- a/backends/advanced/init.py +++ b/backends/advanced/init.py @@ -249,8 +249,6 @@ def setup_llm(self): model = self.prompt_value("Ollama model", "llama3.2") - # Prompt for Ollama embedder model, defaulting to 'nomic-embed-text:latest' - # IMPORTANT: Ensure this model is capable of generating embeddings. embedder_model = self.prompt_value("Ollama embedder model", "nomic-embed-text:latest") self.config["OLLAMA_BASE_URL"] = base_url From 4567e22a65d1e85995ce1b287f45b7b9e0cce525 Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Wed, 22 Oct 2025 20:01:20 +0530 Subject: [PATCH 10/11] feat: add logging when getting LLM provider from environment fix: MongoDB healthcheck command --- backends/advanced/docker-compose.yml | 2 +- backends/advanced/src/advanced_omi_backend/memory/config.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/backends/advanced/docker-compose.yml b/backends/advanced/docker-compose.yml index 86c10c89..3bab6b7b 100644 --- a/backends/advanced/docker-compose.yml +++ b/backends/advanced/docker-compose.yml @@ -153,7 +153,7 @@ services: volumes: - mongo_data:/data/db healthcheck: - test: ["CMD", "mongosh", "--eval", "db.runCommand('ping')"] + test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand({ ping: 1 })"] interval: 10s timeout: 5s retries: 5 diff --git a/backends/advanced/src/advanced_omi_backend/memory/config.py b/backends/advanced/src/advanced_omi_backend/memory/config.py index 25d02e85..2c55a7b3 100644 --- a/backends/advanced/src/advanced_omi_backend/memory/config.py +++ b/backends/advanced/src/advanced_omi_backend/memory/config.py @@ -148,8 +148,9 @@ def build_memory_config_from_env() -> MemoryConfig: memory_config = config_loader.get_memory_extraction_config() # Get LLM provider from environment - llm_provider = os.getenv("LLM_PROVIDER", "openai").lower() - if llm_provider not in ["openai", "ollama"]: + llm_provider = os.getenv("LLM_PROVIDER", "openai").lower().strip() + memory_logger.info(f"LLM_PROVIDER: {llm_provider}") + if llm_provider not in [p.value for p in LLMProvider]: raise ValueError(f"Unsupported LLM provider: {llm_provider}") llm_config = None From 69fa704d481954f53746f2af7a8f64010c2b866e Mon Sep 17 00:00:00 2001 From: Ritik Khatri Date: Wed, 22 Oct 2025 20:22:05 +0530 Subject: [PATCH 11/11] chore: add ollama configs to env template file --- backends/advanced/.env.template | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backends/advanced/.env.template b/backends/advanced/.env.template index 44a88de6..01724f19 100644 --- a/backends/advanced/.env.template +++ b/backends/advanced/.env.template @@ -29,9 +29,10 @@ OPENAI_MODEL=gpt-4o-mini # For Ollama (OpenAI-compatible mode): # LLM_PROVIDER=ollama -# OPENAI_API_KEY=dummy -# OPENAI_BASE_URL=http://ollama:11434/v1 -# OPENAI_MODEL=llama3.1:latest +# OLLAMA_BASE_URL=dummy +# OLLAMA_BASE_URL=http://ollama:11434/v1 +# OLLAMA_MODEL=llama3.1:latest +# OLLAMA_EMBEDDER_MODEL=nomic-embed-text:latest # ======================================== # CHAT INTERFACE CONFIGURATION (Optional)