Download src/config.py from nikeshn/LibBee: direct link, hf CLI and curl.
- Browser
- Download file 6.07 kB
-
https://huggingface.co/spaces/nikeshn/LibBee/resolve/main/src/config.py
- Command line
-
hf download hf://spaces/nikeshn/LibBee/src/config.py
-
curl -L -o config.py https://huggingface.co/spaces/nikeshn/LibBee/resolve/main/src/config.py
6.07 kB
| """Environment-backed configuration for LibBee.""" | |
| from functools import lru_cache | |
| from pathlib import Path | |
| from typing import Literal | |
| from pydantic import field_validator | |
| from pydantic_settings import BaseSettings, SettingsConfigDict | |
| LIBBEE_VERSION = "4.1.2" | |
| class Settings(BaseSettings): | |
| model_config = SettingsConfigDict(case_sensitive=False, env_file=".env", env_file_encoding="utf-8", extra="ignore") | |
| openai_api_key: str = "" | |
| anthropic_api_key: str = "" | |
| primo_api_key: str = "" | |
| # Optional HF variable. "auto" preserves the existing EU/NA/AP discovery; | |
| # selecting the institution's gateway avoids that discovery on each search. | |
| primo_api_region: Literal["auto", "eu", "na", "ap", "ca", "aps", "cn"] = "auto" | |
| openalex_api_key: str = "" | |
| contact_email: str = "libse@ku.ac.ae" | |
| # The Worker sends this secret in X-LibBee-Origin-Token. Production | |
| # protected routes fail closed when the value is missing. | |
| origin_token: str = "" | |
| environment: Literal["development", "production", "test"] = "production" | |
| allowed_cors_origins: str = "http://localhost:8080,http://127.0.0.1:5500" | |
| admin_password: str = "" | |
| session_secret: str = "change-me" | |
| maintenance_mode: bool = False | |
| maintenance_message: str = "LibBee is receiving an update. Please try again shortly." | |
| max_results: int = 5 | |
| max_question_chars: int = 2000 | |
| max_history_messages: int = 12 | |
| max_message_chars: int = 4000 | |
| max_concurrent_agent_requests: int = 20 | |
| # Includes the entire JSON envelope and UTF-8 history. The original 32 KiB | |
| # ceiling rejected otherwise valid conversations under the model limits. | |
| max_request_body_bytes: int = 524_288 | |
| # /data survives HF Space restarts when persistent storage is attached. | |
| runtime_dir: str = "/data/libbee_runtime" | |
| feedback_store_path: str = "" | |
| metrics_store_path: str = "" | |
| config_store_path: str = "" | |
| rag_index_dir: str = "" | |
| knowledge_dir: str = "" | |
| # The authenticated admin page receives only a short-lived signed token; | |
| # the permanent shared secret is never serialized into browser HTML. | |
| cloudflare_worker_url: str = "" | |
| cloudflare_admin_token: str = "" | |
| # HF talks to LibCal directly because some hosted environments cannot open | |
| # outbound connections to shared workers.dev hostnames. | |
| libcal_client_id: str = "" | |
| libcal_client_secret: str = "" | |
| libcal_events_client_id: str = "" | |
| libcal_events_client_secret: str = "" | |
| def reasonable_max_results(cls, value: int) -> int: | |
| if not 1 <= value <= 20: | |
| raise ValueError("max_results must be between 1 and 20") | |
| return value | |
| def reasonable_text_limit(cls, value: int, info) -> int: | |
| ceiling = 2000 if info.field_name == "max_question_chars" else 4000 | |
| if not 256 <= value <= ceiling: | |
| raise ValueError(f"{info.field_name} must be between 256 and {ceiling}") | |
| return value | |
| def reasonable_history_limit(cls, value: int) -> int: | |
| if not 0 <= value <= 12: | |
| raise ValueError("max_history_messages must be between 0 and 12") | |
| return value | |
| def reasonable_concurrency(cls, value: int) -> int: | |
| if not 1 <= value <= 100: | |
| raise ValueError("max_concurrent_agent_requests must be between 1 and 100") | |
| return value | |
| def reasonable_body_limit(cls, value: int) -> int: | |
| if not 16_384 <= value <= 2_097_152: | |
| raise ValueError("max_request_body_bytes must be between 16 KiB and 2 MiB") | |
| return value | |
| def runtime_defaults(self) -> dict: | |
| """One source of defaults for admin, public config, and agent replies.""" | |
| return { | |
| "max_results": self.max_results, | |
| "maintenance_mode": self.maintenance_mode, | |
| "welcome_message": "Hi! I'm LibBee, the Khalifa University Library AI Assistant.", | |
| "custom_instructions": "", | |
| "announcement": "", | |
| "maintenance_message": self.maintenance_message, | |
| } | |
| def cors_origins(self) -> list[str]: | |
| return [value.strip().rstrip("/") for value in self.allowed_cors_origins.split(",") if value.strip()] | |
| def runtime_path(self) -> Path: | |
| requested = Path(self.runtime_dir) | |
| # Honour explicit paths, including nested directories not created yet. | |
| # Only the absent default HF mount falls back to ephemeral local disk. | |
| if self.runtime_dir == "/data/libbee_runtime" and not Path("/data").is_dir(): | |
| return Path("/tmp/libbee_runtime") | |
| return requested | |
| def feedback_path(self) -> Path: | |
| return Path(self.feedback_store_path) if self.feedback_store_path else self.runtime_path / "feedback.jsonl" | |
| def metrics_path(self) -> Path: | |
| return Path(self.metrics_store_path) if self.metrics_store_path else self.runtime_path / "metrics.json" | |
| def config_path(self) -> Path: | |
| return Path(self.config_store_path) if self.config_store_path else self.runtime_path / "runtime_config.json" | |
| def rag_cache_dir(self) -> Path: | |
| return Path(self.rag_index_dir) if self.rag_index_dir else self.runtime_path / "rag_cache" | |
| def kb_dir(self) -> Path: | |
| if self.knowledge_dir: | |
| return Path(self.knowledge_dir) | |
| if Path("/app/data/knowledge").exists(): | |
| return Path("/app/data/knowledge") | |
| return Path("data/knowledge") | |
| def get_settings() -> Settings: | |
| settings = Settings() | |
| settings.runtime_path.mkdir(parents=True, exist_ok=True) | |
| settings.rag_cache_dir.mkdir(parents=True, exist_ok=True) | |
| return settings | |