Added settings service and added post endpoint to edit them
This commit is contained in:
parent
8dc737c124
commit
03b827f3e0
6 changed files with 475 additions and 28 deletions
33
config.yaml
Normal file
33
config.yaml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# OpenRAG Configuration File
|
||||
# This file allows you to configure OpenRAG settings.
|
||||
# Environment variables will override these settings unless edited is true.
|
||||
|
||||
# Track if this config has been manually edited (prevents env var overrides)
|
||||
edited: false
|
||||
|
||||
# Model provider configuration
|
||||
provider:
|
||||
# Supported providers: "openai", "anthropic", "azure", etc.
|
||||
model_provider: "openai"
|
||||
# API key for the model provider (can also be set via OPENAI_API_KEY env var)
|
||||
api_key: ""
|
||||
|
||||
# Knowledge base and document processing configuration
|
||||
knowledge:
|
||||
# Embedding model for vector search
|
||||
embedding_model: "text-embedding-3-small"
|
||||
# Text chunk size for document processing
|
||||
chunk_size: 1000
|
||||
# Overlap between chunks
|
||||
chunk_overlap: 200
|
||||
# Enable OCR for image processing
|
||||
ocr: true
|
||||
# Enable picture descriptions using vision models
|
||||
picture_descriptions: false
|
||||
|
||||
# AI agent configuration
|
||||
agent:
|
||||
# Language model for the chat agent
|
||||
llm_model: "gpt-4o-mini"
|
||||
# System prompt for the agent
|
||||
system_prompt: "You are a helpful AI assistant with access to a knowledge base. Answer questions based on the provided context."
|
||||
|
|
@ -1,6 +1,37 @@
|
|||
# Configuration
|
||||
|
||||
OpenRAG uses environment variables for configuration. Copy `.env.example` to `.env` and populate with your values:
|
||||
OpenRAG supports multiple configuration methods with the following priority:
|
||||
|
||||
1. **Environment Variables** (highest priority)
|
||||
2. **Configuration File** (`config.yaml`)
|
||||
3. **Langflow Flow Settings** (runtime override)
|
||||
4. **Default Values** (fallback)
|
||||
|
||||
## Configuration File
|
||||
|
||||
Create a `config.yaml` file in the project root to configure OpenRAG:
|
||||
|
||||
```yaml
|
||||
# OpenRAG Configuration File
|
||||
provider:
|
||||
model_provider: "openai" # openai, anthropic, azure, etc.
|
||||
api_key: "your-api-key" # or use OPENAI_API_KEY env var
|
||||
|
||||
knowledge:
|
||||
embedding_model: "text-embedding-3-small"
|
||||
chunk_size: 1000
|
||||
chunk_overlap: 200
|
||||
ocr: true
|
||||
picture_descriptions: false
|
||||
|
||||
agent:
|
||||
llm_model: "gpt-4o-mini"
|
||||
system_prompt: "You are a helpful AI assistant..."
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Environment variables will override configuration file settings. You can still use `.env` files:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
|
|
@ -8,20 +39,20 @@ cp .env.example .env
|
|||
|
||||
## Required Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `OPENAI_API_KEY` | Your OpenAI API key |
|
||||
| `OPENSEARCH_PASSWORD` | Password for OpenSearch admin user |
|
||||
| `LANGFLOW_SUPERUSER` | Langflow admin username |
|
||||
| `LANGFLOW_SUPERUSER_PASSWORD` | Langflow admin password |
|
||||
| `LANGFLOW_CHAT_FLOW_ID` | ID of your Langflow chat flow |
|
||||
| `LANGFLOW_INGEST_FLOW_ID` | ID of your Langflow ingestion flow |
|
||||
| `NUDGES_FLOW_ID` | ID of your Langflow nudges/suggestions flow |
|
||||
| Variable | Description |
|
||||
| ----------------------------- | ------------------------------------------- |
|
||||
| `OPENAI_API_KEY` | Your OpenAI API key |
|
||||
| `OPENSEARCH_PASSWORD` | Password for OpenSearch admin user |
|
||||
| `LANGFLOW_SUPERUSER` | Langflow admin username |
|
||||
| `LANGFLOW_SUPERUSER_PASSWORD` | Langflow admin password |
|
||||
| `LANGFLOW_CHAT_FLOW_ID` | ID of your Langflow chat flow |
|
||||
| `LANGFLOW_INGEST_FLOW_ID` | ID of your Langflow ingestion flow |
|
||||
| `NUDGES_FLOW_ID` | ID of your Langflow nudges/suggestions flow |
|
||||
|
||||
## Ingestion Configuration
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| Variable | Description |
|
||||
| ------------------------------ | ------------------------------------------------------ |
|
||||
| `DISABLE_INGEST_WITH_LANGFLOW` | Disable Langflow ingestion pipeline (default: `false`) |
|
||||
|
||||
- `false` or unset: Uses Langflow pipeline (upload → ingest → delete)
|
||||
|
|
@ -29,15 +60,44 @@ cp .env.example .env
|
|||
|
||||
## Optional Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `LANGFLOW_PUBLIC_URL` | Public URL for Langflow (default: `http://localhost:7860`) |
|
||||
| `GOOGLE_OAUTH_CLIENT_ID` / `GOOGLE_OAUTH_CLIENT_SECRET` | Google OAuth authentication |
|
||||
| `MICROSOFT_GRAPH_OAUTH_CLIENT_ID` / `MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET` | Microsoft OAuth |
|
||||
| `WEBHOOK_BASE_URL` | Base URL for webhook endpoints |
|
||||
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | AWS integrations |
|
||||
| `SESSION_SECRET` | Session management (default: auto-generated, change in production) |
|
||||
| `LANGFLOW_KEY` | Explicit Langflow API key (auto-generated if not provided) |
|
||||
| `LANGFLOW_SECRET_KEY` | Secret key for Langflow internal operations |
|
||||
| Variable | Description |
|
||||
| ------------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
||||
| `LANGFLOW_PUBLIC_URL` | Public URL for Langflow (default: `http://localhost:7860`) |
|
||||
| `GOOGLE_OAUTH_CLIENT_ID` / `GOOGLE_OAUTH_CLIENT_SECRET` | Google OAuth authentication |
|
||||
| `MICROSOFT_GRAPH_OAUTH_CLIENT_ID` / `MICROSOFT_GRAPH_OAUTH_CLIENT_SECRET` | Microsoft OAuth |
|
||||
| `WEBHOOK_BASE_URL` | Base URL for webhook endpoints |
|
||||
| `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` | AWS integrations |
|
||||
| `SESSION_SECRET` | Session management (default: auto-generated, change in production) |
|
||||
| `LANGFLOW_KEY` | Explicit Langflow API key (auto-generated if not provided) |
|
||||
| `LANGFLOW_SECRET_KEY` | Secret key for Langflow internal operations |
|
||||
|
||||
## OpenRAG Configuration Variables
|
||||
|
||||
These environment variables override settings in `config.yaml`:
|
||||
|
||||
### Provider Settings
|
||||
|
||||
| Variable | Description | Default |
|
||||
| ------------------ | ---------------------------------------- | -------- |
|
||||
| `MODEL_PROVIDER` | Model provider (openai, anthropic, etc.) | `openai` |
|
||||
| `PROVIDER_API_KEY` | API key for the model provider | |
|
||||
| `OPENAI_API_KEY` | OpenAI API key (backward compatibility) | |
|
||||
|
||||
### Knowledge Settings
|
||||
|
||||
| Variable | Description | Default |
|
||||
| ------------------------------ | --------------------------------------- | ------------------------ |
|
||||
| `EMBEDDING_MODEL` | Embedding model for vector search | `text-embedding-3-small` |
|
||||
| `CHUNK_SIZE` | Text chunk size for document processing | `1000` |
|
||||
| `CHUNK_OVERLAP` | Overlap between chunks | `200` |
|
||||
| `OCR_ENABLED` | Enable OCR for image processing | `true` |
|
||||
| `PICTURE_DESCRIPTIONS_ENABLED` | Enable picture descriptions | `false` |
|
||||
|
||||
### Agent Settings
|
||||
|
||||
| Variable | Description | Default |
|
||||
| --------------- | --------------------------------- | ------------------------ |
|
||||
| `LLM_MODEL` | Language model for the chat agent | `gpt-4o-mini` |
|
||||
| `SYSTEM_PROMPT` | System prompt for the agent | Default assistant prompt |
|
||||
|
||||
See `.env.example` for a complete list with descriptions, and `docker-compose*.yml` for runtime usage.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ from config.settings import (
|
|||
LANGFLOW_INGEST_FLOW_ID,
|
||||
LANGFLOW_PUBLIC_URL,
|
||||
clients,
|
||||
get_openrag_config,
|
||||
config_manager,
|
||||
)
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
|
@ -15,12 +17,34 @@ logger = get_logger(__name__)
|
|||
async def get_settings(request, session_manager):
|
||||
"""Get application settings"""
|
||||
try:
|
||||
openrag_config = get_openrag_config()
|
||||
|
||||
provider_config = openrag_config.provider
|
||||
knowledge_config = openrag_config.knowledge
|
||||
agent_config = openrag_config.agent
|
||||
# Return public settings that are safe to expose to frontend
|
||||
settings = {
|
||||
"langflow_url": LANGFLOW_URL,
|
||||
"flow_id": LANGFLOW_CHAT_FLOW_ID,
|
||||
"ingest_flow_id": LANGFLOW_INGEST_FLOW_ID,
|
||||
"langflow_public_url": LANGFLOW_PUBLIC_URL,
|
||||
"edited": openrag_config.edited,
|
||||
# OpenRAG configuration
|
||||
"provider": {
|
||||
"model_provider": provider_config.model_provider,
|
||||
# Note: API key is not exposed for security
|
||||
},
|
||||
"knowledge": {
|
||||
"embedding_model": knowledge_config.embedding_model,
|
||||
"chunk_size": knowledge_config.chunk_size,
|
||||
"chunk_overlap": knowledge_config.chunk_overlap,
|
||||
"ocr": knowledge_config.ocr,
|
||||
"picture_descriptions": knowledge_config.picture_descriptions,
|
||||
},
|
||||
"agent": {
|
||||
"llm_model": agent_config.llm_model,
|
||||
"system_prompt": agent_config.system_prompt,
|
||||
},
|
||||
}
|
||||
|
||||
# Only expose edit URLs when a public URL is configured
|
||||
|
|
@ -35,7 +59,7 @@ async def get_settings(request, session_manager):
|
|||
)
|
||||
|
||||
# Fetch ingestion flow configuration to get actual component defaults
|
||||
if LANGFLOW_INGEST_FLOW_ID:
|
||||
if LANGFLOW_INGEST_FLOW_ID and openrag_config.edited:
|
||||
try:
|
||||
response = await clients.langflow_request(
|
||||
"GET",
|
||||
|
|
@ -45,11 +69,12 @@ async def get_settings(request, session_manager):
|
|||
flow_data = response.json()
|
||||
|
||||
# Extract component defaults (ingestion-specific settings only)
|
||||
# Start with configured defaults
|
||||
ingestion_defaults = {
|
||||
"chunkSize": 1000,
|
||||
"chunkOverlap": 200,
|
||||
"separator": "\\n",
|
||||
"embeddingModel": "text-embedding-3-small",
|
||||
"chunkSize": knowledge_config.chunk_size,
|
||||
"chunkOverlap": knowledge_config.chunk_overlap,
|
||||
"separator": "\\n", # Keep hardcoded for now as it's not in config
|
||||
"embeddingModel": knowledge_config.embedding_model,
|
||||
}
|
||||
|
||||
if flow_data.get("data", {}).get("nodes"):
|
||||
|
|
@ -104,3 +129,105 @@ async def get_settings(request, session_manager):
|
|||
return JSONResponse(
|
||||
{"error": f"Failed to retrieve settings: {str(e)}"}, status_code=500
|
||||
)
|
||||
|
||||
|
||||
async def update_settings(request, session_manager):
|
||||
"""Update application settings"""
|
||||
try:
|
||||
# Get current configuration
|
||||
current_config = get_openrag_config()
|
||||
|
||||
# Check if config is marked as edited
|
||||
if not current_config.edited:
|
||||
return JSONResponse(
|
||||
{"error": "Configuration must be marked as edited before updates are allowed"},
|
||||
status_code=403
|
||||
)
|
||||
|
||||
# Parse request body
|
||||
body = await request.json()
|
||||
|
||||
# Validate allowed fields
|
||||
allowed_fields = {
|
||||
"llm_model", "system_prompt", "ocr", "picture_descriptions",
|
||||
"chunk_size", "chunk_overlap"
|
||||
}
|
||||
|
||||
# Check for invalid fields
|
||||
invalid_fields = set(body.keys()) - allowed_fields
|
||||
if invalid_fields:
|
||||
return JSONResponse(
|
||||
{"error": f"Invalid fields: {', '.join(invalid_fields)}. Allowed fields: {', '.join(allowed_fields)}"},
|
||||
status_code=400
|
||||
)
|
||||
|
||||
# Update configuration
|
||||
config_updated = False
|
||||
|
||||
# Update agent settings
|
||||
if "llm_model" in body:
|
||||
current_config.agent.llm_model = body["llm_model"]
|
||||
config_updated = True
|
||||
|
||||
if "system_prompt" in body:
|
||||
current_config.agent.system_prompt = body["system_prompt"]
|
||||
config_updated = True
|
||||
|
||||
# Update knowledge settings
|
||||
if "ocr" in body:
|
||||
if not isinstance(body["ocr"], bool):
|
||||
return JSONResponse(
|
||||
{"error": "ocr must be a boolean value"},
|
||||
status_code=400
|
||||
)
|
||||
current_config.knowledge.ocr = body["ocr"]
|
||||
config_updated = True
|
||||
|
||||
if "picture_descriptions" in body:
|
||||
if not isinstance(body["picture_descriptions"], bool):
|
||||
return JSONResponse(
|
||||
{"error": "picture_descriptions must be a boolean value"},
|
||||
status_code=400
|
||||
)
|
||||
current_config.knowledge.picture_descriptions = body["picture_descriptions"]
|
||||
config_updated = True
|
||||
|
||||
if "chunk_size" in body:
|
||||
if not isinstance(body["chunk_size"], int) or body["chunk_size"] <= 0:
|
||||
return JSONResponse(
|
||||
{"error": "chunk_size must be a positive integer"},
|
||||
status_code=400
|
||||
)
|
||||
current_config.knowledge.chunk_size = body["chunk_size"]
|
||||
config_updated = True
|
||||
|
||||
if "chunk_overlap" in body:
|
||||
if not isinstance(body["chunk_overlap"], int) or body["chunk_overlap"] < 0:
|
||||
return JSONResponse(
|
||||
{"error": "chunk_overlap must be a non-negative integer"},
|
||||
status_code=400
|
||||
)
|
||||
current_config.knowledge.chunk_overlap = body["chunk_overlap"]
|
||||
config_updated = True
|
||||
|
||||
if not config_updated:
|
||||
return JSONResponse(
|
||||
{"error": "No valid fields provided for update"},
|
||||
status_code=400
|
||||
)
|
||||
|
||||
# Save the updated configuration
|
||||
if config_manager.save_config_file(current_config):
|
||||
logger.info("Configuration updated successfully", updated_fields=list(body.keys()))
|
||||
return JSONResponse({"message": "Configuration updated successfully"})
|
||||
else:
|
||||
return JSONResponse(
|
||||
{"error": "Failed to save configuration"},
|
||||
status_code=500
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to update settings", error=str(e))
|
||||
return JSONResponse(
|
||||
{"error": f"Failed to update settings: {str(e)}"}, status_code=500
|
||||
)
|
||||
|
|
|
|||
197
src/config/config_manager.py
Normal file
197
src/config/config_manager.py
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
"""Configuration management for OpenRAG."""
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any, Optional
|
||||
from dataclasses import dataclass, asdict
|
||||
from utils.logging_config import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ProviderConfig:
|
||||
"""Model provider configuration."""
|
||||
model_provider: str = "openai" # openai, anthropic, etc.
|
||||
api_key: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class KnowledgeConfig:
|
||||
"""Knowledge/ingestion configuration."""
|
||||
embedding_model: str = "text-embedding-3-small"
|
||||
chunk_size: int = 1000
|
||||
chunk_overlap: int = 200
|
||||
ocr: bool = True
|
||||
picture_descriptions: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
class AgentConfig:
|
||||
"""Agent configuration."""
|
||||
llm_model: str = "gpt-4o-mini"
|
||||
system_prompt: str = "You are a helpful AI assistant with access to a knowledge base. Answer questions based on the provided context."
|
||||
|
||||
|
||||
@dataclass
|
||||
class OpenRAGConfig:
|
||||
"""Complete OpenRAG configuration."""
|
||||
provider: ProviderConfig
|
||||
knowledge: KnowledgeConfig
|
||||
agent: AgentConfig
|
||||
edited: bool = False # Track if manually edited
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> "OpenRAGConfig":
|
||||
"""Create config from dictionary."""
|
||||
return cls(
|
||||
provider=ProviderConfig(**data.get("provider", {})),
|
||||
knowledge=KnowledgeConfig(**data.get("knowledge", {})),
|
||||
agent=AgentConfig(**data.get("agent", {}))
|
||||
)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert config to dictionary."""
|
||||
return asdict(self)
|
||||
|
||||
|
||||
class ConfigManager:
|
||||
"""Manages OpenRAG configuration from multiple sources."""
|
||||
|
||||
def __init__(self, config_file: Optional[str] = None):
|
||||
"""Initialize configuration manager.
|
||||
|
||||
Args:
|
||||
config_file: Path to configuration file. Defaults to 'config.yaml' in project root.
|
||||
"""
|
||||
self.config_file = Path(config_file) if config_file else Path("config.yaml")
|
||||
self._config: Optional[OpenRAGConfig] = None
|
||||
|
||||
def load_config(self) -> OpenRAGConfig:
|
||||
"""Load configuration from environment variables and config file.
|
||||
|
||||
Priority order:
|
||||
1. Environment variables (highest)
|
||||
2. Configuration file
|
||||
3. Defaults (lowest)
|
||||
"""
|
||||
if self._config is not None:
|
||||
return self._config
|
||||
|
||||
# Start with defaults
|
||||
config_data = {
|
||||
"provider": {},
|
||||
"knowledge": {},
|
||||
"agent": {}
|
||||
}
|
||||
|
||||
# Load from config file if it exists
|
||||
if self.config_file.exists():
|
||||
try:
|
||||
with open(self.config_file, 'r') as f:
|
||||
file_config = yaml.safe_load(f) or {}
|
||||
|
||||
# Merge file config
|
||||
for section in ["provider", "knowledge", "agent"]:
|
||||
if section in file_config:
|
||||
config_data[section].update(file_config[section])
|
||||
|
||||
logger.info(f"Loaded configuration from {self.config_file}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to load config file {self.config_file}: {e}")
|
||||
|
||||
# Create config object first to check edited flags
|
||||
temp_config = OpenRAGConfig.from_dict(config_data)
|
||||
|
||||
# Override with environment variables (highest priority, but respect edited flags)
|
||||
self._load_env_overrides(config_data, temp_config)
|
||||
|
||||
# Create config object
|
||||
self._config = OpenRAGConfig.from_dict(config_data)
|
||||
|
||||
logger.debug("Configuration loaded", config=self._config.to_dict())
|
||||
return self._config
|
||||
|
||||
def _load_env_overrides(self, config_data: Dict[str, Any], temp_config: Optional["OpenRAGConfig"] = None) -> None:
|
||||
"""Load environment variable overrides, respecting edited flag."""
|
||||
|
||||
# Skip all environment overrides if config has been manually edited
|
||||
if temp_config and temp_config.edited:
|
||||
logger.debug("Skipping all env overrides - config marked as edited")
|
||||
return
|
||||
|
||||
# Provider settings
|
||||
if os.getenv("MODEL_PROVIDER"):
|
||||
config_data["provider"]["model_provider"] = os.getenv("MODEL_PROVIDER")
|
||||
if os.getenv("PROVIDER_API_KEY"):
|
||||
config_data["provider"]["api_key"] = os.getenv("PROVIDER_API_KEY")
|
||||
# Backward compatibility for OpenAI
|
||||
if os.getenv("OPENAI_API_KEY"):
|
||||
config_data["provider"]["api_key"] = os.getenv("OPENAI_API_KEY")
|
||||
if not config_data["provider"].get("model_provider"):
|
||||
config_data["provider"]["model_provider"] = "openai"
|
||||
|
||||
# Knowledge settings
|
||||
if os.getenv("EMBEDDING_MODEL"):
|
||||
config_data["knowledge"]["embedding_model"] = os.getenv("EMBEDDING_MODEL")
|
||||
if os.getenv("CHUNK_SIZE"):
|
||||
config_data["knowledge"]["chunk_size"] = int(os.getenv("CHUNK_SIZE"))
|
||||
if os.getenv("CHUNK_OVERLAP"):
|
||||
config_data["knowledge"]["chunk_overlap"] = int(os.getenv("CHUNK_OVERLAP"))
|
||||
if os.getenv("OCR_ENABLED"):
|
||||
config_data["knowledge"]["ocr"] = os.getenv("OCR_ENABLED").lower() in ("true", "1", "yes")
|
||||
if os.getenv("PICTURE_DESCRIPTIONS_ENABLED"):
|
||||
config_data["knowledge"]["picture_descriptions"] = os.getenv("PICTURE_DESCRIPTIONS_ENABLED").lower() in ("true", "1", "yes")
|
||||
|
||||
# Agent settings
|
||||
if os.getenv("LLM_MODEL"):
|
||||
config_data["agent"]["llm_model"] = os.getenv("LLM_MODEL")
|
||||
if os.getenv("SYSTEM_PROMPT"):
|
||||
config_data["agent"]["system_prompt"] = os.getenv("SYSTEM_PROMPT")
|
||||
|
||||
def get_config(self) -> OpenRAGConfig:
|
||||
"""Get current configuration, loading if necessary."""
|
||||
if self._config is None:
|
||||
return self.load_config()
|
||||
return self._config
|
||||
|
||||
def reload_config(self) -> OpenRAGConfig:
|
||||
"""Force reload configuration from sources."""
|
||||
self._config = None
|
||||
return self.load_config()
|
||||
|
||||
def save_config_file(self, config: Optional[OpenRAGConfig] = None) -> bool:
|
||||
"""Save configuration to file.
|
||||
|
||||
Args:
|
||||
config: Configuration to save. If None, uses current config.
|
||||
|
||||
Returns:
|
||||
True if saved successfully, False otherwise.
|
||||
"""
|
||||
if config is None:
|
||||
config = self.get_config()
|
||||
|
||||
# Mark config as edited when saving
|
||||
config.edited = True
|
||||
|
||||
try:
|
||||
# Ensure directory exists
|
||||
self.config_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with open(self.config_file, 'w') as f:
|
||||
yaml.dump(config.to_dict(), f, default_flow_style=False, indent=2)
|
||||
|
||||
# Update cached config to reflect the edited flags
|
||||
self._config = config
|
||||
|
||||
logger.info(f"Configuration saved to {self.config_file} - marked as edited")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to save configuration to {self.config_file}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
# Global config manager instance
|
||||
config_manager = ConfigManager()
|
||||
|
|
@ -17,6 +17,9 @@ load_dotenv("../")
|
|||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
# Import configuration manager
|
||||
from .config_manager import config_manager
|
||||
|
||||
# Environment variables
|
||||
OPENSEARCH_HOST = os.getenv("OPENSEARCH_HOST", "localhost")
|
||||
OPENSEARCH_PORT = int(os.getenv("OPENSEARCH_PORT", "9200"))
|
||||
|
|
@ -398,3 +401,21 @@ class AppClients:
|
|||
|
||||
# Global clients instance
|
||||
clients = AppClients()
|
||||
|
||||
# Configuration access
|
||||
def get_openrag_config():
|
||||
"""Get current OpenRAG configuration."""
|
||||
return config_manager.get_config()
|
||||
|
||||
# Expose configuration settings for backward compatibility and easy access
|
||||
def get_provider_config():
|
||||
"""Get provider configuration."""
|
||||
return get_openrag_config().provider
|
||||
|
||||
def get_knowledge_config():
|
||||
"""Get knowledge configuration."""
|
||||
return get_openrag_config().knowledge
|
||||
|
||||
def get_agent_config():
|
||||
"""Get agent configuration."""
|
||||
return get_openrag_config().agent
|
||||
|
|
|
|||
11
src/main.py
11
src/main.py
|
|
@ -890,7 +890,7 @@ async def create_app():
|
|||
),
|
||||
methods=["POST"],
|
||||
),
|
||||
# Settings endpoint
|
||||
# Settings endpoints
|
||||
Route(
|
||||
"/settings",
|
||||
require_auth(services["session_manager"])(
|
||||
|
|
@ -900,6 +900,15 @@ async def create_app():
|
|||
),
|
||||
methods=["GET"],
|
||||
),
|
||||
Route(
|
||||
"/settings",
|
||||
require_auth(services["session_manager"])(
|
||||
partial(
|
||||
settings.update_settings, session_manager=services["session_manager"]
|
||||
)
|
||||
),
|
||||
methods=["POST"],
|
||||
),
|
||||
Route(
|
||||
"/nudges",
|
||||
require_auth(services["session_manager"])(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue