Add fail-safe mode to embedding and OpenSearch components

Introduces a 'fail_safe_mode' option to the Embedding Model and OpenSearch (Multi-Model Multi-Embedding) components, allowing errors to be logged and None returned instead of raising exceptions. Refactors embedding model fetching logic for better error handling and updates component metadata, field order, and dependencies. Also adds 'className' fields and updates frontend node folder IDs for improved UI consistency.
This commit is contained in:
Edwin Jose 2025-11-26 01:15:30 -05:00
parent 2fa6efeaa9
commit 998d8b9195
5 changed files with 306 additions and 46 deletions

File diff suppressed because one or more lines are too long

View file

@ -14,6 +14,7 @@ from config.settings import (
clients,
get_openrag_config,
config_manager,
is_no_auth_mode,
)
from api.provider_validation import validate_provider_setup
@ -637,6 +638,41 @@ async def update_settings(request, session_manager):
logger.info(
f"Set SELECTED_EMBEDDING_MODEL global variable to {current_config.knowledge.embedding_model}"
)
# Update MCP servers with provider credentials
try:
from services.langflow_mcp_service import LangflowMCPService
from utils.langflow_headers import build_mcp_global_vars_from_config
mcp_service = LangflowMCPService()
# Build global vars using utility function
mcp_global_vars = build_mcp_global_vars_from_config(current_config)
# In no-auth mode, add the anonymous JWT token and user details
if is_no_auth_mode() and session_manager:
from session_manager import AnonymousUser
# Create/get anonymous JWT for no-auth mode
anonymous_jwt = session_manager.get_effective_jwt_token(None, None)
if anonymous_jwt:
mcp_global_vars["JWT"] = anonymous_jwt
# Add anonymous user details
anonymous_user = AnonymousUser()
mcp_global_vars["OWNER"] = anonymous_user.user_id # "anonymous"
mcp_global_vars["OWNER_NAME"] = f'"{anonymous_user.name}"' # "Anonymous User" (quoted)
mcp_global_vars["OWNER_EMAIL"] = anonymous_user.email # "anonymous@localhost"
logger.debug("Added anonymous JWT and user details to MCP servers for no-auth mode")
if mcp_global_vars:
result = await mcp_service.update_mcp_servers_with_global_vars(mcp_global_vars)
logger.info("Updated MCP servers with provider credentials after settings change", **result)
except Exception as mcp_error:
logger.warning(f"Failed to update MCP servers after settings change: {str(mcp_error)}")
# Don't fail the entire settings update if MCP update fails
except Exception as e:
logger.error(f"Failed to update Langflow settings: {str(e)}")
@ -655,7 +691,7 @@ async def update_settings(request, session_manager):
)
async def onboarding(request, flows_service):
async def onboarding(request, flows_service, session_manager=None):
"""Handle onboarding configuration setup"""
try:
# Get current configuration
@ -943,6 +979,41 @@ async def onboarding(request, flows_service):
logger.info(
f"Set SELECTED_EMBEDDING_MODEL global variable to {current_config.knowledge.embedding_model}"
)
# Update MCP servers with provider credentials during onboarding
try:
from services.langflow_mcp_service import LangflowMCPService
from utils.langflow_headers import build_mcp_global_vars_from_config
mcp_service = LangflowMCPService()
# Build global vars using utility function
mcp_global_vars = build_mcp_global_vars_from_config(current_config)
# In no-auth mode, add the anonymous JWT token and user details
if is_no_auth_mode() and session_manager:
from session_manager import AnonymousUser
# Create/get anonymous JWT for no-auth mode
anonymous_jwt = session_manager.get_effective_jwt_token(None, None)
if anonymous_jwt:
mcp_global_vars["JWT"] = anonymous_jwt
# Add anonymous user details
anonymous_user = AnonymousUser()
mcp_global_vars["OWNER"] = anonymous_user.user_id # "anonymous"
mcp_global_vars["OWNER_NAME"] = f'"{anonymous_user.name}"' # "Anonymous User" (quoted)
mcp_global_vars["OWNER_EMAIL"] = anonymous_user.email # "anonymous@localhost"
logger.debug("Added anonymous JWT and user details to MCP servers for no-auth mode during onboarding")
if mcp_global_vars:
result = await mcp_service.update_mcp_servers_with_global_vars(mcp_global_vars)
logger.info("Updated MCP servers with provider credentials during onboarding", **result)
except Exception as mcp_error:
logger.warning(f"Failed to update MCP servers during onboarding: {str(mcp_error)}")
# Don't fail onboarding if MCP update fails
except Exception as e:
logger.error(

View file

@ -433,6 +433,55 @@ async def _ingest_default_documents_openrag(services, file_paths):
)
async def _update_mcp_servers_with_provider_credentials(services):
"""Update MCP servers with provider credentials at startup.
This is especially important for no-auth mode where users don't go through
the OAuth login flow that would normally set these credentials.
"""
try:
auth_service = services.get("auth_service")
session_manager = services.get("session_manager")
if not auth_service or not auth_service.langflow_mcp_service:
logger.debug("MCP service not available, skipping credential update")
return
config = get_openrag_config()
# Build global vars with provider credentials using utility function
from utils.langflow_headers import build_mcp_global_vars_from_config
global_vars = build_mcp_global_vars_from_config(config)
# In no-auth mode, add the anonymous JWT token and user details
if is_no_auth_mode() and session_manager:
from session_manager import AnonymousUser
# Create/get anonymous JWT for no-auth mode
anonymous_jwt = session_manager.get_effective_jwt_token(None, None)
if anonymous_jwt:
global_vars["JWT"] = anonymous_jwt
# Add anonymous user details
anonymous_user = AnonymousUser()
global_vars["OWNER"] = anonymous_user.user_id # "anonymous"
global_vars["OWNER_NAME"] = f'"{anonymous_user.name}"' # "Anonymous User" (quoted for spaces)
global_vars["OWNER_EMAIL"] = anonymous_user.email # "anonymous@localhost"
logger.info("Added anonymous JWT and user details to MCP servers for no-auth mode")
if global_vars:
result = await auth_service.langflow_mcp_service.update_mcp_servers_with_global_vars(global_vars)
logger.info("Updated MCP servers with provider credentials at startup", **result)
else:
logger.debug("No provider credentials configured, skipping MCP server update")
except Exception as e:
logger.warning("Failed to update MCP servers with provider credentials at startup", error=str(e))
# Don't fail startup if MCP update fails
async def startup_tasks(services):
"""Startup tasks"""
logger.info("Starting startup tasks")
@ -445,6 +494,9 @@ async def startup_tasks(services):
# Configure alerting security
await configure_alerting_security()
# Update MCP servers with provider credentials (especially important for no-auth mode)
await _update_mcp_servers_with_provider_credentials(services)
async def initialize_services():
@ -1052,7 +1104,11 @@ async def create_app():
Route(
"/onboarding",
require_auth(services["session_manager"])(
partial(settings.onboarding, flows_service=services["flows_service"])
partial(
settings.onboarding,
flows_service=services["flows_service"],
session_manager=services["session_manager"]
)
),
methods=["POST"],
),

View file

@ -308,6 +308,16 @@ class AuthService:
global_vars["OWNER_NAME"] = str(f"\"{owner_name}\"")
if user_info.get("email"):
global_vars["OWNER_EMAIL"] = user_info.get("email")
# Add provider credentials to MCP servers using utility function
from config.settings import get_openrag_config
from utils.langflow_headers import build_mcp_global_vars_from_config
config = get_openrag_config()
provider_vars = build_mcp_global_vars_from_config(config)
# Merge provider credentials with user info
global_vars.update(provider_vars)
# Run in background to avoid delaying login flow
task = asyncio.create_task(

View file

@ -31,3 +31,41 @@ def add_provider_credentials_to_headers(headers: Dict[str, str], config) -> None
ollama_endpoint = transform_localhost_url(config.providers.ollama.endpoint)
headers["X-LANGFLOW-GLOBAL-VAR-OLLAMA_BASE_URL"] = str(ollama_endpoint)
def build_mcp_global_vars_from_config(config) -> Dict[str, str]:
"""Build MCP global variables dictionary from OpenRAG configuration.
Args:
config: OpenRAGConfig object containing provider configurations
Returns:
Dictionary of global variables for MCP servers (without X-Langflow-Global-Var prefix)
"""
global_vars = {}
# Add OpenAI credentials
if config.providers.openai.api_key:
global_vars["OPENAI_API_KEY"] = config.providers.openai.api_key
# Add Anthropic credentials
if config.providers.anthropic.api_key:
global_vars["ANTHROPIC_API_KEY"] = config.providers.anthropic.api_key
# Add WatsonX credentials
if config.providers.watsonx.api_key:
global_vars["WATSONX_API_KEY"] = config.providers.watsonx.api_key
if config.providers.watsonx.project_id:
global_vars["WATSONX_PROJECT_ID"] = config.providers.watsonx.project_id
# Add Ollama endpoint (with localhost transformation)
if config.providers.ollama.endpoint:
ollama_endpoint = transform_localhost_url(config.providers.ollama.endpoint)
global_vars["OLLAMA_BASE_URL"] = ollama_endpoint
# Add selected embedding model
if config.knowledge.embedding_model:
global_vars["SELECTED_EMBEDDING_MODEL"] = config.knowledge.embedding_model
return global_vars