Update 5 files
- /rag/config_models.py - /rag/utils/config_loader.py - /rag/rag_orchestrator.py - /rag/rag_server.py - /rag/rag_api.py
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
Модели данных для конфигурации на основе Pydantic.
|
||||
Используются для загрузки и валидации настроек из YAML-файлов (rag.conf и bot.conf).
|
||||
Обеспечивают строгую типизацию и автоматическую проверку обязательных полей.
|
||||
|
||||
Добавлены прокси-свойства для обратной совместимости с BotConfig.
|
||||
"""
|
||||
|
||||
from typing import Optional, List, Dict, Any
|
||||
@@ -18,7 +20,6 @@ class DatabaseConfig(BaseModel):
|
||||
host: str = Field(..., description="Хост базы данных")
|
||||
port: int = Field(5432, description="Порт PostgreSQL")
|
||||
user: str = Field(..., description="Имя пользователя")
|
||||
password_env: str = Field(..., description="Имя переменной окружения с паролем")
|
||||
database: str = Field(..., description="Имя базы данных")
|
||||
ssl: bool = Field(False, description="Использовать SSL")
|
||||
ssl_mode: Optional[str] = Field("prefer", description="Режим SSL (require, prefer, disable)")
|
||||
@@ -42,7 +43,7 @@ class QdrantConfig(BaseModel):
|
||||
|
||||
class GigaChatConfig(BaseModel):
|
||||
"""Настройки GigaChat API."""
|
||||
credentials_env: str = Field(..., description="Имя переменной окружения с API-ключом")
|
||||
api_key: Optional[str] = Field(None, description="API-ключ (загружается из окружения)")
|
||||
model_embedding: str = Field("Embeddings", description="Модель для эмбеддингов")
|
||||
model_generation: str = Field("GigaChat-Max", description="Модель для генерации")
|
||||
timeout: int = Field(600, description="Таймаут запросов в секундах")
|
||||
@@ -164,10 +165,15 @@ class PromptsConfig(BaseModel):
|
||||
consistency_max_fragments: int = Field(5, description="Максимальное количество фрагментов для проверки противоречий")
|
||||
critique: PromptTemperatures = Field(default_factory=lambda: PromptTemperatures(temperature=0.1))
|
||||
rerank: PromptTemperatures = Field(default_factory=lambda: PromptTemperatures(temperature=0.1))
|
||||
rerank_min_length: int = Field(5000, description="Минимальная длина контекста для переранжирования")
|
||||
generate_document: PromptTemperatures = Field(default_factory=lambda: PromptTemperatures(temperature=0.1))
|
||||
|
||||
|
||||
class WebScraperConfig(BaseModel):
|
||||
"""Настройки веб-скрапера."""
|
||||
max_pages: int = Field(5, description="Максимальное количество страниц для рекурсивного обхода")
|
||||
max_depth: int = Field(1, description="Максимальная глубина рекурсии")
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Главная модель конфигурации приложения
|
||||
# ============================================================
|
||||
@@ -179,7 +185,6 @@ class AppConfig(BaseModel):
|
||||
"""
|
||||
name: str = Field(..., description="Имя профиля бота")
|
||||
jid: str = Field(..., description="JID бота (user@domain)")
|
||||
password_env: str = Field(..., description="Имя переменной окружения с паролем XMPP")
|
||||
resource: str = Field("bot", description="Ресурс XMPP")
|
||||
status_message: str = Field(..., description="Сообщение статуса присутствия")
|
||||
xmpp_server: Optional[str] = Field(None, description="XMPP сервер (если не указан, берётся из JID)")
|
||||
@@ -188,6 +193,8 @@ class AppConfig(BaseModel):
|
||||
admin_jids: List[str] = Field([], description="Список JID администраторов")
|
||||
log_level: str = Field("INFO", description="Уровень логирования")
|
||||
rag_server_url: str = Field("http://localhost:8080", description="URL RAG-сервера")
|
||||
xmpp_password: Optional[str] = Field(None, description="Пароль XMPP (из окружения)")
|
||||
salute_speech_auth: Optional[str] = Field(None, description="Авторизация для SaluteSpeech (из окружения)")
|
||||
|
||||
# Секции
|
||||
database: DatabaseConfig
|
||||
@@ -205,14 +212,9 @@ class AppConfig(BaseModel):
|
||||
file_permissions: FilePermissionsConfig
|
||||
ai: AIConfig
|
||||
prompts: PromptsConfig
|
||||
web_scraper: WebScraperConfig = Field(default_factory=WebScraperConfig)
|
||||
|
||||
# Дополнительные вычисляемые поля (заполняются при загрузке)
|
||||
xmpp_password: Optional[str] = Field(None, description="Пароль XMPP (загружается из окружения)")
|
||||
gigachat_api_key: Optional[str] = Field(None, description="API-ключ GigaChat (из окружения)")
|
||||
db_password: Optional[str] = Field(None, description="Пароль PostgreSQL (из окружения)")
|
||||
salute_speech_auth: Optional[str] = Field(None, description="Авторизация для SaluteSpeech (из окружения)")
|
||||
|
||||
# Пути (преобразуются в Path при загрузке)
|
||||
# Дополнительные поля для путей (заполняются при загрузке)
|
||||
profile_dir: Optional[Path] = Field(None, description="Корень профиля")
|
||||
data_dir_path: Optional[Path] = Field(None)
|
||||
temp_dir_path: Optional[Path] = Field(None)
|
||||
@@ -224,5 +226,306 @@ class AppConfig(BaseModel):
|
||||
# Промпты (загружаются из файлов)
|
||||
prompts_content: Optional[Dict[str, str]] = Field(default_factory=dict, description="Содержимое промптов")
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Прокси-свойства для обратной совместимости со старым BotConfig
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# База данных
|
||||
@property
|
||||
def db_host(self) -> str:
|
||||
return self.database.host
|
||||
|
||||
@property
|
||||
def db_port(self) -> int:
|
||||
return self.database.port
|
||||
|
||||
@property
|
||||
def db_user(self) -> str:
|
||||
return self.database.user
|
||||
|
||||
@property
|
||||
def db_password(self) -> str:
|
||||
return self.database.password
|
||||
|
||||
@property
|
||||
def db_name(self) -> str:
|
||||
return self.database.database
|
||||
|
||||
@property
|
||||
def db_ssl(self) -> bool:
|
||||
return self.database.ssl
|
||||
|
||||
@property
|
||||
def db_ssl_mode(self) -> Optional[str]:
|
||||
return self.database.ssl_mode
|
||||
|
||||
# Qdrant
|
||||
@property
|
||||
def qdrant_host(self) -> str:
|
||||
return self.qdrant.host
|
||||
|
||||
@property
|
||||
def qdrant_port(self) -> int:
|
||||
return self.qdrant.port
|
||||
|
||||
@property
|
||||
def qdrant_grpc_port(self) -> int:
|
||||
return self.qdrant.grpc_port
|
||||
|
||||
@property
|
||||
def qdrant_collection(self) -> str:
|
||||
return self.qdrant.collection
|
||||
|
||||
@property
|
||||
def qdrant_vector_size(self) -> int:
|
||||
return self.qdrant.vector_size
|
||||
|
||||
@property
|
||||
def qdrant_distance(self) -> str:
|
||||
return self.qdrant.distance
|
||||
|
||||
# GigaChat
|
||||
@property
|
||||
def gigachat_api_key(self) -> Optional[str]:
|
||||
return self.gigachat.api_key
|
||||
|
||||
@property
|
||||
def gigachat_model_embedding(self) -> str:
|
||||
return self.gigachat.model_embedding
|
||||
|
||||
@property
|
||||
def gigachat_model_generation(self) -> str:
|
||||
return self.gigachat.model_generation
|
||||
|
||||
@property
|
||||
def gigachat_timeout(self) -> int:
|
||||
return self.gigachat.timeout
|
||||
|
||||
@property
|
||||
def gigachat_temperature(self) -> float:
|
||||
return self.gigachat.temperature
|
||||
|
||||
# Embedding
|
||||
@property
|
||||
def embedding_cache_size(self) -> int:
|
||||
return self.embedding.cache_size
|
||||
|
||||
@property
|
||||
def embedding_model(self) -> str:
|
||||
return self.embedding.model
|
||||
|
||||
@property
|
||||
def embedding_timeout(self) -> int:
|
||||
return self.embedding.timeout
|
||||
|
||||
@property
|
||||
def embedding_verify_ssl(self) -> bool:
|
||||
return self.embedding.verify_ssl_certs
|
||||
|
||||
# Chunking
|
||||
@property
|
||||
def chunking_enabled(self) -> bool:
|
||||
return self.chunking.enabled
|
||||
|
||||
@property
|
||||
def chunk_size_tokens(self) -> int:
|
||||
return self.chunking.chunk_size_tokens
|
||||
|
||||
@property
|
||||
def overlap_tokens(self) -> int:
|
||||
return self.chunking.overlap_tokens
|
||||
|
||||
@property
|
||||
def chunking_strategy(self) -> str:
|
||||
return self.chunking.strategy
|
||||
|
||||
@property
|
||||
def chunking_approx_chunk_chars(self) -> int:
|
||||
return self.chunking.approx_chunk_chars
|
||||
|
||||
@property
|
||||
def chunking_approx_overlap_chars(self) -> int:
|
||||
return self.chunking.approx_overlap_chars
|
||||
|
||||
# RAG
|
||||
@property
|
||||
def rag_default_top_k(self) -> int:
|
||||
return self.rag.default_top_k
|
||||
|
||||
@property
|
||||
def rag_metrics_top_k(self) -> int:
|
||||
return self.rag.metrics_top_k
|
||||
|
||||
@property
|
||||
def rag_contradiction_top_k(self) -> int:
|
||||
return self.rag.contradiction_top_k
|
||||
|
||||
@property
|
||||
def max_context_tokens(self) -> int:
|
||||
return self.rag.max_context_tokens
|
||||
|
||||
@property
|
||||
def reserved_for_answer_tokens(self) -> int:
|
||||
return self.rag.reserved_for_answer_tokens
|
||||
|
||||
@property
|
||||
def reserved_for_overhead_tokens(self) -> int:
|
||||
return self.rag.reserved_for_overhead_tokens
|
||||
|
||||
@property
|
||||
def max_model_tokens(self) -> int:
|
||||
return self.rag.max_model_tokens
|
||||
|
||||
@property
|
||||
def rerank_min_length(self) -> int:
|
||||
return self.rag.rerank_min_length
|
||||
|
||||
# HTTP
|
||||
@property
|
||||
def http_download_timeout(self) -> int:
|
||||
return self.http.download_timeout
|
||||
|
||||
@property
|
||||
def http_upload_timeout(self) -> int:
|
||||
return self.http.upload_timeout
|
||||
|
||||
# Features
|
||||
@property
|
||||
def file_processing(self) -> bool:
|
||||
return self.features.file_processing
|
||||
|
||||
@property
|
||||
def surgical_replace(self) -> bool:
|
||||
return self.features.surgical_replace
|
||||
|
||||
@property
|
||||
def voice_recognition(self) -> bool:
|
||||
return self.features.voice_recognition
|
||||
|
||||
@property
|
||||
def vision(self) -> bool:
|
||||
return self.features.vision
|
||||
|
||||
@property
|
||||
def archive_support(self) -> bool:
|
||||
return self.features.archive_support
|
||||
|
||||
@property
|
||||
def ocr(self) -> bool:
|
||||
return self.features.ocr
|
||||
|
||||
@property
|
||||
def allow_public_knowledge(self) -> bool:
|
||||
return self.features.allow_public_knowledge
|
||||
|
||||
@property
|
||||
def max_file_size_mb(self) -> int:
|
||||
return self.features.max_file_size_mb
|
||||
|
||||
@property
|
||||
def max_archive_files(self) -> int:
|
||||
return self.features.max_archive_files
|
||||
|
||||
@property
|
||||
def enable_intent_classification(self) -> bool:
|
||||
return self.features.enable_intent_classification
|
||||
|
||||
@property
|
||||
def enable_self_critique(self) -> bool:
|
||||
return self.features.enable_self_critique
|
||||
|
||||
@property
|
||||
def surgical_keywords(self) -> List[str]:
|
||||
return self.features.surgical_keywords
|
||||
|
||||
@property
|
||||
def mention_keyword(self) -> Optional[str]:
|
||||
return self.features.mention_keyword
|
||||
|
||||
# AI
|
||||
@property
|
||||
def ai_model(self) -> str:
|
||||
return self.ai.model or self.gigachat.model_generation
|
||||
|
||||
@property
|
||||
def ai_temperature(self) -> float:
|
||||
return self.ai.temperature
|
||||
|
||||
@property
|
||||
def ai_timeout(self) -> int:
|
||||
return self.ai.timeout
|
||||
|
||||
# Cleanup
|
||||
@property
|
||||
def temp_cleanup_days(self) -> int:
|
||||
return self.cleanup.temp_days
|
||||
|
||||
@property
|
||||
def upload_cleanup_days(self) -> int:
|
||||
return self.cleanup.upload_days
|
||||
|
||||
@property
|
||||
def cleanup_interval(self) -> int:
|
||||
return self.cleanup.interval_seconds
|
||||
|
||||
@property
|
||||
def user_data_cleanup_days(self) -> int:
|
||||
return self.cleanup.user_data_days
|
||||
|
||||
# Web scraper
|
||||
@property
|
||||
def ws_max_pages(self) -> int:
|
||||
return self.web_scraper.max_pages
|
||||
|
||||
@property
|
||||
def ws_max_depth(self) -> int:
|
||||
return self.web_scraper.max_depth
|
||||
|
||||
# Prompts temperatures
|
||||
@property
|
||||
def intent_temperature(self) -> float:
|
||||
return self.prompts.intent.temperature
|
||||
|
||||
@property
|
||||
def expand_temperature(self) -> float:
|
||||
return self.prompts.expand.temperature
|
||||
|
||||
@property
|
||||
def metrics_temperature(self) -> float:
|
||||
return self.prompts.metrics.temperature
|
||||
|
||||
@property
|
||||
def summary_temperature(self) -> float:
|
||||
return self.prompts.summary.temperature
|
||||
|
||||
@property
|
||||
def summary_max_chars(self) -> int:
|
||||
return self.prompts.summary_max_chars
|
||||
|
||||
@property
|
||||
def consistency_temperature(self) -> float:
|
||||
return self.prompts.consistency.temperature
|
||||
|
||||
@property
|
||||
def consistency_max_fragments(self) -> int:
|
||||
return self.prompts.consistency_max_fragments
|
||||
|
||||
@property
|
||||
def critique_temperature(self) -> float:
|
||||
return self.prompts.critique.temperature
|
||||
|
||||
@property
|
||||
def rerank_temperature(self) -> float:
|
||||
return self.prompts.rerank.temperature
|
||||
|
||||
@property
|
||||
def generate_document_temperature(self) -> float:
|
||||
return self.prompts.generate_document.temperature
|
||||
|
||||
# File permissions
|
||||
@property
|
||||
def file_mode(self) -> int:
|
||||
return int(self.file_permissions.mode, 8)
|
||||
|
||||
class Config:
|
||||
extra = "forbid" # Запрещаем неизвестные поля
|
||||
Reference in New Issue
Block a user