sangsangfinder / api /core /config.py
cksleigen's picture
Initial clean deploy
54656fc
Raw
History Blame Contribute Delete
8.13 kB
import os
import re
from datetime import datetime
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
_BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
VECTOR_DB = os.getenv("VECTOR_DB", "pinecone").lower()
EMBED_MODEL_PATH = os.path.join(_BASE_DIR, "models", "embed_finetuned")
SUMMARY_MODEL_PATH = os.path.join(_BASE_DIR, "models", "summary_finetuned")
CLASSIFY_MODEL_PATH = os.path.join(_BASE_DIR, "models", "classify_finetuned")
BASE_MODEL_EMBED = os.getenv("BASE_MODEL_EMBED", "BAAI/bge-m3")
EMBEDDER_BACKEND = os.getenv("EMBEDDER_BACKEND", "sentence-transformers").lower()
EMBEDDING_DEVICE = os.getenv("EMBEDDING_DEVICE", "").strip().lower()
SIMCSE_POOLING = os.getenv("SIMCSE_POOLING", "cls").lower()
SEARCH_ALPHA = float(os.getenv("SEARCH_ALPHA", "0.5"))
VECTOR_STATE_PATH = os.getenv(
"VECTOR_STATE_PATH",
os.path.join(_BASE_DIR, "pinecone_index"),
)
INDEX_MANIFEST_PATH = os.path.join(VECTOR_STATE_PATH, "index_manifest.json")
NOTICES_CACHE_PATH = os.path.join(_BASE_DIR, "data", "data_2026.json")
PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
PINECONE_INDEX_NAME = os.getenv("PINECONE_INDEX_NAME", "hansung-notices-bge-m3")
PINECONE_CLOUD = os.getenv("PINECONE_CLOUD", "aws")
PINECONE_REGION = os.getenv("PINECONE_REGION", "us-east-1")
PINECONE_NAMESPACE = os.getenv("PINECONE_NAMESPACE", "prod")
PINECONE_CACHE_PATH = os.getenv(
"PINECONE_CACHE_PATH",
os.path.join(VECTOR_STATE_PATH, "pinecone_chunks.json"),
)
EMBEDDING_DIM = int(os.getenv("EMBEDDING_DIM", "1024"))
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
GEMINI_API_KEY_PAID_TIER = os.getenv("GEMINI_API_KEY_PAID_TIER")
GEMINI_ROUTER_TIMEOUT_SECONDS = int(os.getenv("GEMINI_ROUTER_TIMEOUT_SECONDS", "5"))
GEMINI_REPLY_TIMEOUT_SECONDS = int(os.getenv("GEMINI_REPLY_TIMEOUT_SECONDS", "15"))
QUERY_ROUTING_ENABLED = os.getenv("QUERY_ROUTING_ENABLED", "false").lower() == "true"
GEMINI_FEATURE_TIMEOUT_SECONDS = int(os.getenv("GEMINI_FEATURE_TIMEOUT_SECONDS", "10"))
GEMINI_FEATURE_MODEL = os.getenv("GEMINI_FEATURE_MODEL", "gemini-2.5-flash-lite")
GEMINI_FEATURE_BATCH_SIZE = int(os.getenv("GEMINI_FEATURE_BATCH_SIZE", "8"))
GEMINI_FEATURE_EXTRACTION_ENABLED = os.getenv("GEMINI_FEATURE_EXTRACTION_ENABLED", "true").lower() == "true"
NOTICE_FEATURE_CACHE_PATH = os.getenv(
"NOTICE_FEATURE_CACHE_PATH",
os.path.join(_BASE_DIR, "data", "notice_feature_cache.json"),
)
BOARD_LIST_URL = "https://www.hansung.ac.kr/bbs/hansung/2127/artclList.do"
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"}
TARGET_YEAR = str(datetime.now().year)
CHUNK_SIZE = 500
CHUNK_OVERLAP = 80
CATEGORIES = [
"์ทจ์—…/์ฑ„์šฉ", "์ธํ„ด์‹ญ", "์žฅํ•™๊ธˆ", "ํ•™์ž๊ธˆ/๊ทผ๋กœ์žฅํ•™", "ํ•™์‚ฌํ–‰์ •",
"์ฐฝ์—…", "๊ตญ์ œ๊ต๋ฅ˜", "๊ต์œก/ํŠน๊ฐ•", "๋น„๊ต๊ณผ", "๊ณต๋ชจ์ „/๊ฒฝ์ง„๋Œ€ํšŒ",
"๋ด‰์‚ฌ/์„œํฌํ„ฐ์ฆˆ", "๊ธฐ์ˆ™์‚ฌ/์ƒํ™œ๊ด€", "ROTC", "๊ธฐํƒ€",
]
CATEGORY_PREFIX: dict[str, str] = {
"์ฑ„์šฉ์ •๋ณด": "์ทจ์—…/์ฑ„์šฉ",
"๊ฐ•์†Œ๊ธฐ์—…์ฑ„์šฉ": "์ทจ์—…/์ฑ„์šฉ",
"์ธํ„ด์‰ฝ": "์ธํ„ด์‹ญ",
"๊ต์™ธ์žฅํ•™๊ธˆ": "์žฅํ•™๊ธˆ",
"๊ตญ๊ฐ€์žฅํ•™๊ธˆ": "์žฅํ•™๊ธˆ",
"ํ•™์ž๊ธˆ๋Œ€์ถœ": "ํ•™์ž๊ธˆ/๊ทผ๋กœ์žฅํ•™",
"๊ตญ๊ฐ€๊ทผ๋กœ": "ํ•™์ž๊ธˆ/๊ทผ๋กœ์žฅํ•™",
"๋ฉดํ•™๊ทผ๋กœ": "ํ•™์ž๊ธˆ/๊ทผ๋กœ์žฅํ•™",
"๊ณต๋ชจ์ „": "๊ณต๋ชจ์ „/๊ฒฝ์ง„๋Œ€ํšŒ",
"์ •๋ณด": "๊ณต๋ชจ์ „/๊ฒฝ์ง„๋Œ€ํšŒ",
}
CATEGORY_KEYWORDS: dict[str, list[str]] = {
"ROTC": ["ROTC", "ํ•™๊ตฐ์‚ฌ๊ด€", "ํ•™๊ตฐ๋‹จ", "ํ˜„์—ญ๋ณ‘ ๋ชจ์ง‘", "ํ˜„์—ญ๋ณ‘๋ชจ์ง‘", "์˜ˆ๋น„๊ตฐ", "์ „๋ฌธ์‚ฌ๊ด€", "์žฌ๋ณ‘์—ญํŒ์ •๊ฒ€์‚ฌ"],
"๊ธฐ์ˆ™์‚ฌ/์ƒํ™œ๊ด€": ["๊ธฐ์ˆ™์‚ฌ", "์ƒํ™œ๊ด€", "์ƒ์ƒ๋นŒ๋ฆฌ์ง€", "์šฐ์ดŒํ•™์‚ฌ", "์ž„๋Œ€๊ธฐ์ˆ™์‚ฌ", "์‚ฌ๊ฐ", "์ž…์‚ฌ์ƒ ์„ ๋ฐœ", "๋Œ€ํ•™์ƒ์ฃผํƒ", "ํ•™์‚ฌ๊ด€"],
"๋น„๊ต๊ณผ": ["๋น„๊ต๊ณผ", "๋™์•„๋ฆฌ", "D-School", "ํฌ๋Ÿผ", "๋Œ€๋™์ œ", "์˜์ƒ์ œ", "์ž…ํ•™์‹",
"HS CREW", "์ƒ์ƒํŒŒํฌ", "๋ผ์ดํ”„ ๋””์ž์ธ", "๋ฌธํ™”ํƒ๋ฐฉ", "๋งŒ์šฐ์ ˆ", "์˜ค์ฐฌ ์†Œํ†ต",
"Lunch with", "์ฒœ์›์˜ ์•„์นจ๋ฐฅ", "ESG", "์ง„๋กœ์ง‘๋‹จ์ƒ๋‹ด", "๋ฆฌ๋”์‹ญ ํƒํ—˜",
"ํ•™์ƒ์ถ•์ œ", "๋ฌธํ™”์ œ", "ํŽ˜์Šคํ‹ฐ๋ฒŒ", "์†Œ๋ชจ์ž„",
"๋””์ฆˆ๋‹ˆ ํ”„๋กœ๊ทธ๋žจ", "๋””์ฆˆ๋‹ˆํ”„๋กœ๊ทธ๋žจ", "FSU-Disney", "Disney",
"์ƒˆ๋‚ด๊ธฐ ์ƒˆ๋กœ๋ฐฐ์›€ํ„ฐ", "์ƒˆ๋กœ๋ฐฐ์›€ํ„ฐ", "์ดํ•™์ƒํšŒ", "์‚ฌ์ง„์ „", "์˜์ƒยท์‚ฌ์ง„์ „", "์ง„๋กœ ์„ค๋ช…ํšŒ", "ํŠธ๋ž™ ์ง„๋กœ"],
"์ทจ์—…/์ฑ„์šฉ": ["์ฑ„์šฉ", "์‹ ์ž…", "๊ณต์ฑ„", "์ทจ์—…", "์ฑ„์šฉ๋ฐ•๋žŒํšŒ", "์ทจ์—…๋ฐ•๋žŒํšŒ", "๋ชจ์ง‘๊ณต๊ณ ", "์ง๋ฌด", "์ฑ„์šฉ์—ฐ๊ณ„", "์ผ๋ฐ˜์ฑ„์šฉ", "์ถ”์ฒœ์ฑ„์šฉ"],
"์ธํ„ด์‹ญ": ["์ธํ„ด", "์ธํ„ด์‹ญ", "์ผ๊ฒฝํ—˜", "์ฒดํ—˜ํ˜•", "ํ˜„์žฅ์‹ค์Šต", "IPP"],
"์žฅํ•™๊ธˆ": ["์žฅํ•™", "์žฅํ•™์ƒ", "์žฅํ•™์žฌ๋‹จ", "์žฅํ•™๊ธˆ", "๊ธฐ๋ถ€์žฅํ•™", "์žฅํ•™์‚ฌ์—…", "์Šค์นผ๋ผ์‹ญ", "์žฅํ•™์ง€์›"],
"ํ•™์ž๊ธˆ/๊ทผ๋กœ์žฅํ•™": ["ํ•™์ž๊ธˆ๋Œ€์ถœ", "ํ•™์ž๊ธˆ", "์ด์ž์ง€์›", "๊ตญ๊ฐ€๊ทผ๋กœ", "๋ฉดํ•™๊ทผ๋กœ", "๊ทผ๋กœ์žฅํ•™", "๋Œ€์ถœ์ด์ž",
"๋“ฑ๋ก๊ธˆ ๋‚ฉ๋ถ€", "๋“ฑ๋ก๊ธˆ ๋ถ„ํ• ", "ํ•™๊ธฐ์ดˆ๊ณผ์ž ๋“ฑ๋ก๊ธˆ"],
"ํ•™์‚ฌํ–‰์ •": ["์ˆ˜๊ฐ•์‹ ์ฒญ", "์ˆ˜๊ฐ•์ •์ •", "์กธ์—…", "ํœดํ•™", "๋ณตํ•™", "ํ•™์ ", "ํŠธ๋ž™๋ณ€๊ฒฝ", "์„ฑ์ ", "ํ๊ฐ•", "๋ณต์ˆ˜์ „๊ณต", "๋ถ€์ „๊ณต",
"์žฌ์ž…ํ•™", "์—ฐ๊ณ„์ „๊ณต", "Micro Degree", "MD๊ณผ์ •", "๊ต์–‘์˜์–ด", "์ด์ˆ˜์‹ ์ฒญ",
"ํŠธ๋ž™์„ ํƒ", "๊ณ„์ ˆํ•™๊ธฐ", "์ˆ˜์—…ํ‰๊ฐ€", "ํ•™์œ„์ทจ๋“์œ ์˜ˆ", "์ˆ˜๊ฐ•ํฌ๊ธฐ", "์„œ๋ฉด์‹ ์ฒญ", "์„œ๋ฉด ์‹ ์ฒญ",
"๊ต์ฐจ์ „๋ถ€", "ํŽธ์ž…์ƒ", "์ „๋ถ€(๊ณผ)", "ํ•™์œ„์ˆ˜์—ฌ์‹", "ํ•™์‚ฌํ•™์œ„์ทจ๋“",
"์˜ค๋ฆฌ์—”ํ…Œ์ด์…˜", "๋ฐ˜ํŽธ์„ฑ๊ณ ์‚ฌ", "ํ•ฉ๊ฒฉ์ž ๊ณต๊ณ ", "ํ•ฉ๊ฒฉ์ž๋ฐœํ‘œ", "์„ ๋ฐœ ๊ฒฐ๊ณผ", "์ด์ˆ˜ ๋ฉด์ œ",
"์ค‘๊ฐ„๊ณ ์‚ฌ", "๊ธฐ๋ง๊ณ ์‚ฌ", "์ „๊ณต๊ณผ๋ชฉ ๋ณ€๊ฒฝ", "๋‹ค์ „๊ณต ์‹ ์ฒญ", "ํ•™์„์‚ฌ์—ฐ๊ณ„",
"ํ•™์‚ฌ๊ฒฝ๊ณ ", "์ž๊ธฐ์„ค๊ณ„์ „๊ณต", "๊ต์–‘ํ•„์ˆ˜", "์ƒ์ƒ๋ ฅ์ด๋…ธ๋ฒ ์ดํ„ฐ"],
"์ฐฝ์—…": ["์ฐฝ์—…", "์ฐฝ์—…๋™์•„๋ฆฌ", "์ฐฝ์—…์ง€์›", "์ฐฝ์—…๋ฉ˜ํ† ๋ง", "์Šคํƒ€ํŠธ์—…", "์•„์ด๋””์–ดํ†ค", "์ž…์ฃผ๊ธฐ์—…", "์˜ˆ๋น„์ฐฝ์—…", "ํ•™์ƒ CEO", "CEO ๋ฐœ๊ตด"],
"๊ตญ์ œ๊ต๋ฅ˜": ["๊ตํ™˜ํ•™์ƒ", "์–ดํ•™์—ฐ์ˆ˜", "ํŒŒ๊ฒฌ", "๊ธ€๋กœ๋ฒŒ๋ฒ„๋””", "๊ตญ์ œ๊ต๋ฅ˜", "ํ•ด์™ธ", "์–ดํ•™", "๊ธ€๋กœ์ปฌ",
"๊ธ€๋กœ๋ฒŒ ํŠœํ„ฐ๋ง", "๊ธ€๋กœ๋ฒŒ Conversation", "๊ธ€๋กœ๋ฒŒ ์ปจ๋ฒ„์„ธ์ด์…˜", "๊ธ€๋กœ๋ฒŒ ๋ฌธํ™” ์†Œํ†ต",
"๋‹จ๊ธฐ์—ฐ์ˆ˜", "K-Move", "WEST ์—ฐ์ˆ˜", "ํ•œยท๋ฏธ๋Œ€ํ•™์ƒ", "๊ธ€๋กœ๋ฒŒ ๋™ํ–‰"],
"๊ต์œก/ํŠน๊ฐ•": ["ํŠน๊ฐ•", "๊ต์œก์ƒ", "์•„์นด๋ฐ๋ฏธ", "KDT", "K-๋””์ง€ํ„ธ", "๊ฐ•์ขŒ", "๊ต์œก๊ณผ์ •", "์—ญ๋Ÿ‰๊ฐ•ํ™”",
"ํ‰์ƒ๊ต์œก", "RISE", "๋งˆ์ดํฌ๋กœ๋””๊ทธ๋ฆฌ", "TOPCIT", "์—ฐ๊ตฌ๋ฐฉ๋ฒ•๋ก ",
"์ดˆ์ฒญ๊ฐ•์—ฐ", "ํŠน๋ณ„๊ฐ•์—ฐ", "ํ•ต์‹ฌ์—ญ๋Ÿ‰์ง„๋‹จ", "HS-CESA", "K-CESA", "UICA", "K-NSSE",
"ํญ๋ ฅ์˜ˆ๋ฐฉ๊ต์œก", "ํ•„์ˆ˜๊ต์œก", "์ „๋ฌธ๊ณผ์ •", "SW๋งˆ์—์ŠคํŠธ๋กœ", "์ฝ”๋”ฉ ์บ ํ”„", "์ฝ”๋”ฉ์บ ํ”„",
"์—ฐ๊ตฌ์œค๋ฆฌ", "์›Œํฌ์ˆ", "์ง„๋กœ ์บ ํ”„", "์‹ฌํ์†Œ์ƒ์ˆ ", "์ €์ž‘๊ถŒ", "๊ธฐ์ดˆ์—ญ๋Ÿ‰ ๊ฐ€์ด๋“œ"],
"๊ณต๋ชจ์ „/๊ฒฝ์ง„๋Œ€ํšŒ": ["๊ณต๋ชจ์ „", "๊ฒฝ์ง„๋Œ€ํšŒ", "์ฑŒ๋ฆฐ์ง€", "ํ•ด์ปคํ†ค", "๋Œ€ํšŒ", "๊ณต๋ชจ", "๋ฌธํ•™์ƒ"],
"๋ด‰์‚ฌ/์„œํฌํ„ฐ์ฆˆ": ["์„œํฌํ„ฐ์ฆˆ", "์„œํฌํ„ฐ์Šค", "๋ด‰์‚ฌ", "๋ฉ˜ํ† ", "๋ด‰์‚ฌ์ž", "๊ธฐ์ž๋‹จ", "์ž์›ํ™œ๋™", "๋ฉ˜ํ† ๋‹จ", "๋ฉ˜ํ† ๋ง",
"ํ™๋ณด๋Œ€์‚ฌ", "ํ•˜๋ž‘", "์†Œํ†ต-e", "์•ฐ๋ฒ„์„œ๋”", "๋ฐฉ์†ก๊ตญ HBS", "ํ™๋ณด๋‹จ",
"์ˆ˜์Šต๊ธฐ์ž", "์šด์˜์ž๋ฌธ์œ„์›", "๋ชจ๋‹ˆํ„ฐ๋ง๋‹จ", "์ž๋ฌธ๋‹จ",
"๋ฐ”๋กœ์•Œ๋ฆผ๋‹จ", "๊ธฐํš๋‹จ", "์ฒดํ—˜๋‹จ", "๋ฐœ๊ตด๋‹จ", "์ˆœ์ฐฐ๋Œ€", "์ œ์ž‘๋‹จ",
"์ž์›์ง€๋„์ž", "๋ณผ๋Ÿฐํ†ค", "์ฒญ๋ฐฑ๋ฆฌํฌํ„ฐ", "Friends of Korea"],
}
CATEGORY_PATTERN = re.compile(
r"^(ํ•œ์„ฑ๊ณต์ง€|๊ตญ์ œ|ํ•™์‚ฌ|๋น„๊ต๊ณผ|์žฅํ•™|์ทจ์—…|์ง„๋กœ|์ฐฝ์—…|๊ธฐํƒ€|ํ˜„์žฅ์‹ค์Šต|๊ต์œกํ”„๋กœ๊ทธ๋žจ|ํ–‰์‚ฌ|์ผ๋ฐ˜๊ณต์ง€)\s*"
)
SUFFIX_PATTERN = re.compile(r"\s*(์ƒˆ๊ธ€|hot|NEW)\s*$", re.IGNORECASE)