2026-01-10 10:35:21 +08:00
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
2025-11-23 10:55:04 +08:00
|
|
|
|
from functools import lru_cache
|
2026-01-10 10:35:21 +08:00
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
from typing import Tuple, Type
|
|
|
|
|
|
|
2026-01-06 05:21:53 +08:00
|
|
|
|
from pydantic import Field
|
|
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
2026-01-10 10:35:21 +08:00
|
|
|
|
from pydantic_settings.sources import (
|
|
|
|
|
|
DotEnvSettingsSource,
|
|
|
|
|
|
EnvSettingsSource,
|
|
|
|
|
|
PydanticBaseSettingsSource,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _repo_root() -> Path:
|
|
|
|
|
|
# services/ingest_service/app/core/config.py -> .../MNOTE
|
|
|
|
|
|
return Path(__file__).resolve().parents[4]
|
2025-11-23 10:55:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Settings(BaseSettings):
|
2026-01-10 10:35:21 +08:00
|
|
|
|
"""Ingest Service 配置(优先读取仓库根目录的 .env.local/.env)。"""
|
2025-11-23 10:55:04 +08:00
|
|
|
|
|
2026-01-10 10:35:21 +08:00
|
|
|
|
model_config = SettingsConfigDict(
|
|
|
|
|
|
env_file=(
|
|
|
|
|
|
str(_repo_root() / ".env.local"),
|
|
|
|
|
|
str(_repo_root() / ".env"),
|
|
|
|
|
|
),
|
|
|
|
|
|
env_file_encoding="utf-8",
|
|
|
|
|
|
case_sensitive=False,
|
|
|
|
|
|
extra="ignore",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 服务基础
|
2025-11-23 10:55:04 +08:00
|
|
|
|
app_name: str = Field("AIMNOTE Ingest Service", env="INGEST_APP_NAME")
|
|
|
|
|
|
environment: str = Field("development", env="INGEST_ENV")
|
|
|
|
|
|
api_prefix: str = "/api"
|
2026-01-10 10:35:21 +08:00
|
|
|
|
|
|
|
|
|
|
# Supabase(通过 Kong: http://127.0.0.1:18000)
|
|
|
|
|
|
supabase_url: str = Field("http://127.0.0.1:18000", env="SUPABASE_URL")
|
|
|
|
|
|
supabase_service_role_key: str = Field("", env="SUPABASE_SERVICE_ROLE_KEY")
|
|
|
|
|
|
|
|
|
|
|
|
# LightRAG(独立服务 7777)
|
2025-11-23 10:55:04 +08:00
|
|
|
|
lightrag_url: str = Field("http://127.0.0.1:7777", env="LIGHTRAG_URL")
|
2026-01-06 05:21:53 +08:00
|
|
|
|
lightrag_api_key: str = Field("", env="LIGHTRAG_API_KEY")
|
2026-01-10 10:35:21 +08:00
|
|
|
|
|
|
|
|
|
|
# 自动入库(rag_index_sources -> LightRAG)
|
|
|
|
|
|
auto_index_enabled: bool = Field(True, env="AUTO_INDEX_ENABLED")
|
|
|
|
|
|
auto_index_interval_seconds: int = Field(5, env="AUTO_INDEX_INTERVAL_SECONDS")
|
|
|
|
|
|
auto_index_batch_size: int = Field(5, env="AUTO_INDEX_BATCH_SIZE")
|
|
|
|
|
|
auto_index_max_attempts: int = Field(6, env="AUTO_INDEX_MAX_ATTEMPTS")
|
|
|
|
|
|
|
|
|
|
|
|
# 删除宽限期(用于“可撤销删除”):例如用户误删后 10 分钟内可恢复,宽限期内不清理 OCR / Storage / LightRAG 资源
|
|
|
|
|
|
delete_grace_seconds: int = Field(600, env="DELETE_GRACE_SECONDS")
|
|
|
|
|
|
|
|
|
|
|
|
# MinerU(用于 OCR / PDF 结构化解析)
|
|
|
|
|
|
mineru_enabled: bool = Field(True, env="MINERU_ENABLED")
|
|
|
|
|
|
mineru_endpoint: str = Field("", env="MINERU_ENDPOINT")
|
|
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
|
def settings_customise_sources(
|
|
|
|
|
|
cls,
|
|
|
|
|
|
settings_cls: Type[BaseSettings],
|
|
|
|
|
|
init_settings: PydanticBaseSettingsSource,
|
|
|
|
|
|
env_settings: EnvSettingsSource,
|
|
|
|
|
|
dotenv_settings: DotEnvSettingsSource,
|
|
|
|
|
|
file_secret_settings: PydanticBaseSettingsSource,
|
|
|
|
|
|
) -> Tuple[PydanticBaseSettingsSource, ...]:
|
|
|
|
|
|
# 关键点:优先使用 .env.local/.env 覆盖系统环境变量,避免被机器上的全局 env 污染。
|
|
|
|
|
|
return (
|
|
|
|
|
|
dotenv_settings,
|
|
|
|
|
|
env_settings,
|
|
|
|
|
|
init_settings,
|
|
|
|
|
|
file_secret_settings,
|
|
|
|
|
|
)
|
2025-11-23 10:55:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@lru_cache()
|
|
|
|
|
|
def get_settings() -> Settings:
|
|
|
|
|
|
return Settings()
|