Merge remote-tracking branch 'origin/main' into fix/upgrade_path
This commit is contained in:
commit
f0b86c107b
15 changed files with 10629 additions and 4112 deletions
|
|
@ -1,4 +1,4 @@
|
|||
FROM langflowai/langflow-nightly:1.7.0.dev19
|
||||
FROM langflowai/langflow-nightly:1.7.0.dev21
|
||||
|
||||
EXPOSE 7860
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,8 @@ services:
|
|||
- FILENAME=None
|
||||
- MIMETYPE=None
|
||||
- FILESIZE=0
|
||||
- LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=JWT,OPENRAG-QUERY-FILTER,OPENSEARCH_PASSWORD,OWNER,OWNER_NAME,OWNER_EMAIL,CONNECTOR_TYPE,FILENAME,MIMETYPE,FILESIZE
|
||||
- SELECTED_EMBEDDING_MODEL=${SELECTED_EMBEDDING_MODEL:-}
|
||||
- LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=JWT,OPENRAG-QUERY-FILTER,OPENSEARCH_PASSWORD,OWNER,OWNER_NAME,OWNER_EMAIL,CONNECTOR_TYPE,FILENAME,MIMETYPE,FILESIZE,SELECTED_EMBEDDING_MODEL
|
||||
- LANGFLOW_LOG_LEVEL=DEBUG
|
||||
- LANGFLOW_AUTO_LOGIN=${LANGFLOW_AUTO_LOGIN}
|
||||
- LANGFLOW_SUPERUSER=${LANGFLOW_SUPERUSER}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ services:
|
|||
|
||||
openrag-backend:
|
||||
image: langflowai/openrag-backend:${OPENRAG_VERSION:-latest}
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile.backend
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.backend
|
||||
container_name: openrag-backend
|
||||
depends_on:
|
||||
- langflow
|
||||
|
|
@ -87,9 +87,9 @@ services:
|
|||
|
||||
openrag-frontend:
|
||||
image: langflowai/openrag-frontend:${OPENRAG_VERSION:-latest}
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile.frontend
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.frontend
|
||||
container_name: openrag-frontend
|
||||
depends_on:
|
||||
- openrag-backend
|
||||
|
|
@ -102,20 +102,20 @@ services:
|
|||
volumes:
|
||||
- ./flows:/app/flows:U,z
|
||||
image: langflowai/openrag-langflow:${LANGFLOW_VERSION:-latest}
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: Dockerfile.langflow
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.langflow
|
||||
container_name: langflow
|
||||
ports:
|
||||
- "7860:7860"
|
||||
environment:
|
||||
- LANGFLOW_DEACTIVATE_TRACING=true
|
||||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
||||
- WATSONX_API_KEY=${WATSONX_API_KEY}
|
||||
- WATSONX_ENDPOINT=${WATSONX_ENDPOINT}
|
||||
- WATSONX_PROJECT_ID=${WATSONX_PROJECT_ID}
|
||||
- OLLAMA_BASE_URL=${OLLAMA_ENDPOINT}
|
||||
- OPENAI_API_KEY=${OPENAI_API_KEY:-None}
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-None}
|
||||
- WATSONX_API_KEY=${WATSONX_API_KEY:-None}
|
||||
- WATSONX_ENDPOINT=${WATSONX_ENDPOINT:-None}
|
||||
- WATSONX_PROJECT_ID=${WATSONX_PROJECT_ID:-None}
|
||||
- OLLAMA_BASE_URL=${OLLAMA_ENDPOINT:-None}
|
||||
- LANGFLOW_LOAD_FLOWS_PATH=/app/flows
|
||||
- LANGFLOW_SECRET_KEY=${LANGFLOW_SECRET_KEY}
|
||||
- JWT=None
|
||||
|
|
@ -129,7 +129,9 @@ services:
|
|||
- FILENAME=None
|
||||
- MIMETYPE=None
|
||||
- FILESIZE=0
|
||||
- LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=JWT,OPENRAG-QUERY-FILTER,OPENSEARCH_PASSWORD,OWNER,OWNER_NAME,OWNER_EMAIL,CONNECTOR_TYPE,FILENAME,MIMETYPE,FILESIZE
|
||||
- SELECTED_EMBEDDING_MODEL=${SELECTED_EMBEDDING_MODEL:-}
|
||||
- OPENSEARCH_PASSWORD=${OPENSEARCH_PASSWORD}
|
||||
- LANGFLOW_VARIABLES_TO_GET_FROM_ENVIRONMENT=JWT,OPENRAG-QUERY-FILTER,OPENSEARCH_PASSWORD,OWNER,OWNER_NAME,OWNER_EMAIL,CONNECTOR_TYPE,FILENAME,MIMETYPE,FILESIZE,SELECTED_EMBEDDING_MODEL,OPENAI_API_KEY,ANTHROPIC_API_KEY,WATSONX_API_KEY,WATSONX_ENDPOINT,WATSONX_PROJECT_ID,OLLAMA_BASE_URL
|
||||
- LANGFLOW_LOG_LEVEL=DEBUG
|
||||
- LANGFLOW_AUTO_LOGIN=${LANGFLOW_AUTO_LOGIN}
|
||||
- LANGFLOW_SUPERUSER=${LANGFLOW_SUPERUSER}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -91,6 +91,10 @@ export function Navigation({
|
|||
|
||||
const { loading } = useLoadingStore();
|
||||
|
||||
useEffect(() => {
|
||||
console.log("loading", loading);
|
||||
}, [loading]);
|
||||
|
||||
const [previousConversationCount, setPreviousConversationCount] = useState(0);
|
||||
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
||||
const [conversationToDelete, setConversationToDelete] =
|
||||
|
|
@ -391,8 +395,70 @@ export function Navigation({
|
|||
No conversations yet
|
||||
</div>
|
||||
) : (
|
||||
conversations.map((conversation) => (
|
||||
<button
|
||||
<>
|
||||
{/* Optimistic rendering: Show placeholder conversation button while loading */}
|
||||
{(() => {
|
||||
// Show placeholder when:
|
||||
// 1. Loading is true AND conversation doesn't exist yet (creating new conversation), OR
|
||||
// 2. currentConversationId exists but isn't in conversations yet (gap between response and list update)
|
||||
const conversationExists = currentConversationId
|
||||
? conversations.some(
|
||||
(conv) => conv.response_id === currentConversationId,
|
||||
)
|
||||
: false;
|
||||
|
||||
const shouldShowPlaceholder =
|
||||
!conversationExists &&
|
||||
(loading ||
|
||||
(currentConversationId !== null &&
|
||||
currentConversationId !== undefined));
|
||||
|
||||
// Use placeholderConversation if available
|
||||
// Otherwise create a placeholder with currentConversationId if it exists
|
||||
// Or use a temporary ID if we're loading but don't have an ID yet
|
||||
const placeholderToShow =
|
||||
placeholderConversation
|
||||
? placeholderConversation
|
||||
: currentConversationId
|
||||
? {
|
||||
response_id: currentConversationId,
|
||||
title: "",
|
||||
endpoint: endpoint,
|
||||
messages: [],
|
||||
total_messages: 0,
|
||||
}
|
||||
: loading
|
||||
? {
|
||||
response_id: `loading-${Date.now()}`,
|
||||
title: "",
|
||||
endpoint: endpoint,
|
||||
messages: [],
|
||||
total_messages: 0,
|
||||
}
|
||||
: null;
|
||||
|
||||
return (
|
||||
shouldShowPlaceholder &&
|
||||
placeholderToShow && (
|
||||
<button
|
||||
key={placeholderToShow.response_id}
|
||||
type="button"
|
||||
className="w-full px-3 h-11 rounded-lg bg-accent group relative text-left cursor-not-allowed"
|
||||
disabled
|
||||
>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm font-medium text-muted-foreground truncate">
|
||||
<span className="thinking-dots"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
);
|
||||
})()}
|
||||
{conversations.map((conversation) => (
|
||||
<button
|
||||
key={conversation.response_id}
|
||||
type="button"
|
||||
className={`w-full px-3 h-11 rounded-lg group relative text-left ${
|
||||
|
|
@ -467,7 +533,8 @@ export function Navigation({
|
|||
</DropdownMenu>
|
||||
</div>
|
||||
</button>
|
||||
))
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -560,6 +561,9 @@ async def update_settings(request, session_manager):
|
|||
|
||||
# Update global variables
|
||||
await _update_langflow_global_variables(current_config)
|
||||
|
||||
if "embedding_provider" in body or "embedding_model" in body:
|
||||
await _update_mcp_servers_with_provider_credentials(current_config)
|
||||
|
||||
# Update model values if provider or model changed
|
||||
if "llm_provider" in body or "llm_model" in body or "embedding_provider" in body or "embedding_model" in body:
|
||||
|
|
@ -582,7 +586,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
|
||||
|
|
@ -828,6 +832,9 @@ async def onboarding(request, flows_service):
|
|||
current_config.providers.openai.api_key != "" or
|
||||
current_config.providers.anthropic.api_key != ""):
|
||||
await _update_langflow_global_variables(current_config)
|
||||
|
||||
if "embedding_provider" in body or "embedding_model" in body:
|
||||
await _update_mcp_servers_with_provider_credentials(current_config, session_manager)
|
||||
|
||||
# Update model values if provider or model fields were provided
|
||||
if "llm_provider" in body or "llm_model" in body or "embedding_provider" in body or "embedding_model" in body:
|
||||
|
|
@ -973,11 +980,56 @@ async def _update_langflow_global_variables(config):
|
|||
)
|
||||
logger.info("Set OLLAMA_BASE_URL global variable in Langflow")
|
||||
|
||||
if config.knowledge.embedding_model:
|
||||
await clients._create_langflow_global_variable(
|
||||
"SELECTED_EMBEDDING_MODEL", config.knowledge.embedding_model, modify=True
|
||||
)
|
||||
logger.info(
|
||||
f"Set SELECTED_EMBEDDING_MODEL global variable to {config.knowledge.embedding_model}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to update Langflow global variables: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
async def _update_mcp_servers_with_provider_credentials(config, session_manager = None):
|
||||
# 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(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
|
||||
|
||||
|
||||
async def _update_langflow_model_values(config, flows_service):
|
||||
"""Update model values across Langflow flows"""
|
||||
try:
|
||||
|
|
@ -1055,7 +1107,7 @@ async def _update_langflow_chunk_settings(config, flows_service):
|
|||
raise
|
||||
|
||||
|
||||
async def reapply_all_settings():
|
||||
async def reapply_all_settings(session_manager = None):
|
||||
"""
|
||||
Reapply all current configuration settings to Langflow flows and global variables.
|
||||
This is called when flows are detected to have been reset.
|
||||
|
|
@ -1066,6 +1118,11 @@ async def reapply_all_settings():
|
|||
|
||||
logger.info("Reapplying all settings to Langflow flows and global variables")
|
||||
|
||||
if config.knowledge.embedding_model or config.knowledge.embedding_provider:
|
||||
await _update_mcp_servers_with_provider_credentials(config, session_manager)
|
||||
else:
|
||||
logger.info("No embedding model or provider configured, skipping MCP server update")
|
||||
|
||||
# Update all Langflow settings using helper functions
|
||||
try:
|
||||
await _update_langflow_global_variables(config)
|
||||
|
|
|
|||
60
src/main.py
60
src/main.py
|
|
@ -370,7 +370,7 @@ async def _ingest_default_documents_langflow(services, file_paths):
|
|||
|
||||
# Prepare tweaks for default documents with anonymous user metadata
|
||||
default_tweaks = {
|
||||
"OpenSearchHybrid-Ve6bS": {
|
||||
"OpenSearchVectorStoreComponentMultimodalMultiEmbedding-By9U4": {
|
||||
"docs_metadata": [
|
||||
{"key": "owner", "value": None},
|
||||
{"key": "owner_name", "value": anonymous_user.name},
|
||||
|
|
@ -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)
|
||||
|
||||
# Check if flows were reset and reapply settings if config is edited
|
||||
try:
|
||||
|
|
@ -1075,7 +1127,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"],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -743,9 +743,9 @@ class LangflowFileProcessor(TaskProcessor):
|
|||
|
||||
if metadata_tweaks:
|
||||
# Initialize the OpenSearch component tweaks if not already present
|
||||
if "OpenSearchHybrid-Ve6bS" not in final_tweaks:
|
||||
final_tweaks["OpenSearchHybrid-Ve6bS"] = {}
|
||||
final_tweaks["OpenSearchHybrid-Ve6bS"]["docs_metadata"] = metadata_tweaks
|
||||
if "OpenSearchVectorStoreComponentMultimodalMultiEmbedding-By9U4" not in final_tweaks:
|
||||
final_tweaks["OpenSearchVectorStoreComponentMultimodalMultiEmbedding-By9U4"] = {}
|
||||
final_tweaks["OpenSearchVectorStoreComponentMultimodalMultiEmbedding-By9U4"]["docs_metadata"] = metadata_tweaks
|
||||
|
||||
# Process file using langflow service
|
||||
result = await self.langflow_file_service.upload_and_ingest_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(
|
||||
|
|
|
|||
|
|
@ -60,11 +60,22 @@ class ChatService:
|
|||
"LANGFLOW_URL and LANGFLOW_CHAT_FLOW_ID environment variables are required"
|
||||
)
|
||||
|
||||
# Prepare extra headers for JWT authentication
|
||||
# Prepare extra headers for JWT authentication and embedding model
|
||||
extra_headers = {}
|
||||
if jwt_token:
|
||||
extra_headers["X-LANGFLOW-GLOBAL-VAR-JWT"] = jwt_token
|
||||
|
||||
# Pass the selected embedding model as a global variable
|
||||
from config.settings import get_openrag_config
|
||||
from utils.langflow_headers import add_provider_credentials_to_headers
|
||||
|
||||
config = get_openrag_config()
|
||||
embedding_model = config.knowledge.embedding_model
|
||||
extra_headers["X-LANGFLOW-GLOBAL-VAR-SELECTED_EMBEDDING_MODEL"] = embedding_model
|
||||
|
||||
# Add provider credentials to headers
|
||||
add_provider_credentials_to_headers(extra_headers, config)
|
||||
logger.debug(f"[LF] Extra headers {extra_headers}")
|
||||
# Get context variables for filters, limit, and threshold
|
||||
from auth_context import (
|
||||
get_score_threshold,
|
||||
|
|
@ -169,11 +180,22 @@ class ChatService:
|
|||
"LANGFLOW_URL and NUDGES_FLOW_ID environment variables are required"
|
||||
)
|
||||
|
||||
# Prepare extra headers for JWT authentication
|
||||
# Prepare extra headers for JWT authentication and embedding model
|
||||
extra_headers = {}
|
||||
if jwt_token:
|
||||
extra_headers["X-LANGFLOW-GLOBAL-VAR-JWT"] = jwt_token
|
||||
|
||||
# Pass the selected embedding model as a global variable
|
||||
from config.settings import get_openrag_config
|
||||
from utils.langflow_headers import add_provider_credentials_to_headers
|
||||
|
||||
config = get_openrag_config()
|
||||
embedding_model = config.knowledge.embedding_model
|
||||
extra_headers["X-LANGFLOW-GLOBAL-VAR-SELECTED_EMBEDDING_MODEL"] = embedding_model
|
||||
|
||||
# Add provider credentials to headers
|
||||
add_provider_credentials_to_headers(extra_headers, config)
|
||||
|
||||
# Build the complete filter expression like the chat service does
|
||||
filter_expression = {}
|
||||
has_user_filters = False
|
||||
|
|
@ -287,10 +309,22 @@ class ChatService:
|
|||
document_prompt = f"I'm uploading a document called '{filename}'. Here is its content:\n\n{document_content}\n\nPlease confirm you've received this document and are ready to answer questions about it."
|
||||
|
||||
if endpoint == "langflow":
|
||||
# Prepare extra headers for JWT authentication
|
||||
# Prepare extra headers for JWT authentication and embedding model
|
||||
extra_headers = {}
|
||||
if jwt_token:
|
||||
extra_headers["X-LANGFLOW-GLOBAL-VAR-JWT"] = jwt_token
|
||||
|
||||
# Pass the selected embedding model as a global variable
|
||||
from config.settings import get_openrag_config
|
||||
from utils.langflow_headers import add_provider_credentials_to_headers
|
||||
|
||||
config = get_openrag_config()
|
||||
embedding_model = config.knowledge.embedding_model
|
||||
extra_headers["X-LANGFLOW-GLOBAL-VAR-SELECTED_EMBEDDING_MODEL"] = embedding_model
|
||||
|
||||
# Add provider credentials to headers
|
||||
add_provider_credentials_to_headers(extra_headers, config)
|
||||
|
||||
# Ensure the Langflow client exists; try lazy init if needed
|
||||
langflow_client = await clients.ensure_langflow_client()
|
||||
if not langflow_client:
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class LangflowFileService:
|
|||
# Pass JWT token via tweaks using the x-langflow-global-var- pattern
|
||||
if jwt_token:
|
||||
# Using the global variable pattern that Langflow expects for OpenSearch components
|
||||
tweaks["OpenSearchHybrid-Ve6bS"] = {"jwt_token": jwt_token}
|
||||
tweaks["OpenSearchVectorStoreComponentMultimodalMultiEmbedding-By9U4"] = {"jwt_token": jwt_token}
|
||||
logger.debug("[LF] Added JWT token to tweaks for OpenSearch components")
|
||||
else:
|
||||
logger.warning("[LF] No JWT token provided")
|
||||
|
|
@ -112,9 +112,9 @@ class LangflowFileService:
|
|||
logger.info(f"[LF] Metadata tweaks {metadata_tweaks}")
|
||||
# if metadata_tweaks:
|
||||
# # Initialize the OpenSearch component tweaks if not already present
|
||||
# if "OpenSearchHybrid-Ve6bS" not in tweaks:
|
||||
# tweaks["OpenSearchHybrid-Ve6bS"] = {}
|
||||
# tweaks["OpenSearchHybrid-Ve6bS"]["docs_metadata"] = metadata_tweaks
|
||||
# if "OpenSearchVectorStoreComponentMultimodalMultiEmbedding-By9U4" not in tweaks:
|
||||
# tweaks["OpenSearchVectorStoreComponentMultimodalMultiEmbedding-By9U4"] = {}
|
||||
# tweaks["OpenSearchVectorStoreComponentMultimodalMultiEmbedding-By9U4"]["docs_metadata"] = metadata_tweaks
|
||||
# logger.debug(
|
||||
# "[LF] Added metadata to tweaks", metadata_count=len(metadata_tweaks)
|
||||
# )
|
||||
|
|
@ -140,6 +140,13 @@ class LangflowFileService:
|
|||
filename = str(file_tuples[0][0]) if file_tuples and len(file_tuples) > 0 else ""
|
||||
mimetype = str(file_tuples[0][2]) if file_tuples and len(file_tuples) > 0 and len(file_tuples[0]) > 2 else ""
|
||||
|
||||
# Get the current embedding model and provider credentials from config
|
||||
from config.settings import get_openrag_config
|
||||
from utils.langflow_headers import add_provider_credentials_to_headers
|
||||
|
||||
config = get_openrag_config()
|
||||
embedding_model = config.knowledge.embedding_model
|
||||
|
||||
headers={
|
||||
"X-Langflow-Global-Var-JWT": str(jwt_token),
|
||||
"X-Langflow-Global-Var-OWNER": str(owner),
|
||||
|
|
@ -149,7 +156,11 @@ class LangflowFileService:
|
|||
"X-Langflow-Global-Var-FILENAME": filename,
|
||||
"X-Langflow-Global-Var-MIMETYPE": mimetype,
|
||||
"X-Langflow-Global-Var-FILESIZE": str(file_size_bytes),
|
||||
"X-Langflow-Global-Var-SELECTED_EMBEDDING_MODEL": str(embedding_model),
|
||||
}
|
||||
|
||||
# Add provider credentials as global variables for ingestion
|
||||
add_provider_credentials_to_headers(headers, config)
|
||||
logger.info(f"[LF] Headers {headers}")
|
||||
logger.info(f"[LF] Payload {payload}")
|
||||
resp = await clients.langflow_request(
|
||||
|
|
|
|||
71
src/utils/langflow_headers.py
Normal file
71
src/utils/langflow_headers.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
"""Utility functions for building Langflow request headers."""
|
||||
|
||||
from typing import Dict
|
||||
from utils.container_utils import transform_localhost_url
|
||||
|
||||
|
||||
def add_provider_credentials_to_headers(headers: Dict[str, str], config) -> None:
|
||||
"""Add provider credentials to headers as Langflow global variables.
|
||||
|
||||
Args:
|
||||
headers: Dictionary of headers to add credentials to
|
||||
config: OpenRAGConfig object containing provider configurations
|
||||
"""
|
||||
# Add OpenAI credentials
|
||||
if config.providers.openai.api_key:
|
||||
headers["X-LANGFLOW-GLOBAL-VAR-OPENAI_API_KEY"] = str(config.providers.openai.api_key)
|
||||
|
||||
# Add Anthropic credentials
|
||||
if config.providers.anthropic.api_key:
|
||||
headers["X-LANGFLOW-GLOBAL-VAR-ANTHROPIC_API_KEY"] = str(config.providers.anthropic.api_key)
|
||||
|
||||
# Add WatsonX credentials
|
||||
if config.providers.watsonx.api_key:
|
||||
headers["X-LANGFLOW-GLOBAL-VAR-WATSONX_API_KEY"] = str(config.providers.watsonx.api_key)
|
||||
|
||||
if config.providers.watsonx.project_id:
|
||||
headers["X-LANGFLOW-GLOBAL-VAR-WATSONX_PROJECT_ID"] = str(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)
|
||||
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
|
||||
|
||||
Loading…
Add table
Reference in a new issue