Dongjin1203 commited on
Commit
05fc904
ยท
1 Parent(s): 0953caf

fix: Resolve ChromaDB readonly issue

Browse files
Files changed (3) hide show
  1. Dockerfile +6 -6
  2. src/utils/config.py +6 -77
  3. start.sh +25 -0
Dockerfile CHANGED
@@ -20,6 +20,7 @@ ENV HUGGINGFACE_HUB_CACHE=/app/.cache/huggingface/hub
20
  ENV OMP_NUM_THREADS=1
21
  ENV MKL_NUM_THREADS=1
22
  ENV NUMEXPR_NUM_THREADS=1
 
23
 
24
  # ์บ์‹œ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ ๋ฐ ๊ถŒํ•œ ์„ค์ •
25
  RUN mkdir -p /app/.cache/huggingface /app/.streamlit && \
@@ -35,12 +36,11 @@ RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
35
  # ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๋ณต์‚ฌ
36
  COPY . .
37
 
 
 
 
38
  # Streamlit ํฌํŠธ
39
  EXPOSE 7860
40
 
41
- # ์‹คํ–‰
42
- CMD ["streamlit", "run", "src/visualization/chatbot_app.py", \
43
- "--server.port=7860", \
44
- "--server.address=0.0.0.0", \
45
- "--server.headless=true", \
46
- "--server.fileWatcherType=none"]
 
20
  ENV OMP_NUM_THREADS=1
21
  ENV MKL_NUM_THREADS=1
22
  ENV NUMEXPR_NUM_THREADS=1
23
+ ENV CHROMA_DB_PATH=/app/.cache/chroma_db
24
 
25
  # ์บ์‹œ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ ๋ฐ ๊ถŒํ•œ ์„ค์ •
26
  RUN mkdir -p /app/.cache/huggingface /app/.streamlit && \
 
36
  # ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๋ณต์‚ฌ
37
  COPY . .
38
 
39
+ # ์‹œ์ž‘ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
40
+ RUN chmod +x /app/start.sh
41
+
42
  # Streamlit ํฌํŠธ
43
  EXPOSE 7860
44
 
45
+ # ์‹œ์ž‘ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰
46
+ CMD ["/app/start.sh"]
 
 
 
 
src/utils/config.py CHANGED
@@ -18,15 +18,15 @@ class Config:
18
  self.BASE_FOLDER_PATH = "./data/files/"
19
  self.OUTPUT_CHUNKS_PATH = "./data/rag_chunks_final.csv"
20
 
21
- # RAG
22
  self.RAG_INPUT_PATH = "./data/rag_chunks_final.csv"
23
- self.DB_DIRECTORY = "./chroma_db"
24
 
25
  # ===== ์ „์ฒ˜๋ฆฌ ์„ค์ • =====
26
  self.CHUNK_SIZE = 1000
27
  self.CHUNK_OVERLAP = 200
28
  self.SEPARATORS = ["\n\n", "\n", " ", ""]
29
- self.MIN_TEXT_LENGTH = 100 # ์ตœ์†Œ ํ…์ŠคํŠธ ๊ธธ์ด
30
 
31
  # ===== ์ž„๋ฒ ๋”ฉ ์„ค์ • =====
32
  self.EMBEDDING_MODEL_NAME = "text-embedding-3-small"
@@ -42,46 +42,17 @@ class Config:
42
 
43
  # ===== ๊ฒ€์ƒ‰ ์„ค์ • =====
44
  self.DEFAULT_TOP_K = 10
45
- self.DEFAULT_ALPHA = 0.5 # Hybrid Search ๊ฐ€์ค‘์น˜
46
  self.DEFAULT_SEARCH_MODE = "hybrid_rerank"
47
 
48
  # ===== LLM ์„ค์ • =====
49
- self.LLM_MODEL_NAME = "gpt-5-mini"
50
  self.DEFAULT_TEMPERATURE = 0.0
51
  self.DEFAULT_MAX_TOKENS = 1000
52
-
53
- # ========== GGUF ๋ชจ๋ธ ์„ค์ • (์‹ ๊ทœ) ==========
54
- self.GGUF_MODEL_PATH = "./models/Llama-3-Open-Ko-8B.Q4_K_M.gguf"
55
- self.GGUF_N_GPU_LAYERS = 35 # GPU์— ์˜ฌ๋ฆด ๋ ˆ์ด์–ด ์ˆ˜ (0 = CPU๋งŒ, 35 = ์ „์ฒด)
56
- self.GGUF_N_CTX = 16384 # ์ปจํ…์ŠคํŠธ ๊ธธ์ด
57
- self.GGUF_N_THREADS = 8 # CPU ์Šค๋ ˆ๋“œ ์ˆ˜
58
-
59
- self.GGUF_MAX_NEW_TOKENS = 512
60
- self.GGUF_TEMPERATURE = 0.5
61
- self.GGUF_TOP_P = 0.9
62
-
63
- # ========== Model Hub ์„ค์ • (์‹ ๊ทœ) ==========
64
- # Hugging Face Spaces ๋ฐฐํฌ ์‹œ True๋กœ ์„ค์ •
65
- self.USE_MODEL_HUB = os.getenv("USE_MODEL_HUB", "false").lower() == "true"
66
-
67
- # Model Hub ๋ ˆํฌ ์ •๋ณด
68
- self.MODEL_HUB_REPO = "Dongjin1203/RFP_Documents_chatbot" # ์‹ค์ œ ๋ ˆํฌ๋ช…์œผ๋กœ ๋ณ€๊ฒฝ ํ•„์š”
69
- self.MODEL_HUB_FILENAME = "Llama-3-Open-Ko-8B.Q4_K_M.gguf"
70
-
71
- # ๋‹ค์šด๋กœ๋“œ ์บ์‹œ ๋””๋ ‰ํ† ๋ฆฌ
72
- self.MODEL_CACHE_DIR = "./models"
73
 
74
  # ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ
75
  self.SYSTEM_PROMPT = "๋‹น์‹ ์€ RFP(์ œ์•ˆ์š”์ฒญ์„œ) ๋ถ„์„ ๋ฐ ์š”์•ฝ ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค."
76
 
77
- def validate_gguf(self):
78
- """GGUF ๋ชจ๋ธ ์„ค์ • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ"""
79
- if not os.path.exists(self.GGUF_MODEL_PATH):
80
- raise FileNotFoundError(
81
- f"GGUF ๋ชจ๋ธ ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: {self.GGUF_MODEL_PATH}"
82
- )
83
- return True
84
-
85
  def _get_api_key(self) -> str:
86
  """ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ API ํ‚ค ๋กœ๋“œ"""
87
  api_key = os.getenv("OPENAI_API_KEY")
@@ -106,7 +77,6 @@ class Config:
106
  f"ํŒŒ์ผ ํด๋”๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: {self.BASE_FOLDER_PATH}"
107
  )
108
 
109
- # ์ถœ๋ ฅ ํด๋” ์ƒ์„ฑ
110
  output_dir = os.path.dirname(self.OUTPUT_CHUNKS_PATH)
111
  if output_dir:
112
  os.makedirs(output_dir, exist_ok=True)
@@ -118,11 +88,6 @@ class Config:
118
  if not self.OPENAI_API_KEY:
119
  raise ValueError("OPENAI_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค")
120
 
121
- if not os.path.exists(self.RAG_INPUT_PATH):
122
- raise FileNotFoundError(
123
- f"์ž…๋ ฅ ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: {self.RAG_INPUT_PATH}"
124
- )
125
-
126
  return True
127
 
128
  def validate_all(self):
@@ -135,43 +100,7 @@ class Config:
135
  """์„ค์ • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ (ํ•˜์œ„ ํ˜ธํ™˜์„ฑ)"""
136
  return self.validate_preprocess()
137
 
138
- def __repr__(self):
139
- """์„ค์ • ์ •๋ณด ์ถœ๋ ฅ"""
140
- return f"""
141
- Config ์„ค์ •:
142
- [๊ฒฝ๋กœ]
143
- - ๋ฉ”ํƒ€ CSV: {self.META_CSV_PATH}
144
- - ํŒŒ์ผ ํด๋”: {self.BASE_FOLDER_PATH}
145
- - ์ฒญํฌ ์ถœ๋ ฅ: {self.OUTPUT_CHUNKS_PATH}
146
- - DB ๊ฒฝ๋กœ: {self.DB_DIRECTORY}
147
- - ์–ด๋Œ‘ํ„ฐ ๊ฒฝ๋กœ: {self.FINETUNED_ADAPTER_PATH}
148
-
149
- [์ „์ฒ˜๋ฆฌ]
150
- - ์ฒญํฌ ํฌ๊ธฐ: {self.CHUNK_SIZE}
151
- - ์ฒญํฌ ์˜ค๋ฒ„๋žฉ: {self.CHUNK_OVERLAP}
152
-
153
- [๋ชจ๋ธ]
154
- - ์ž„๋ฒ ๋”ฉ: {self.EMBEDDING_MODEL_NAME}
155
- - LLM: {self.LLM_MODEL_NAME}
156
- - Fine-tuned: {self.FINETUNED_BASE_MODEL}
157
-
158
- [๊ฒ€์ƒ‰]
159
- - Top-K: {self.DEFAULT_TOP_K}
160
- - Alpha: {self.DEFAULT_ALPHA}
161
- - ๋ชจ๋“œ: {self.DEFAULT_SEARCH_MODE}
162
-
163
- [์ƒ์„ฑ]
164
- - Temperature: {self.FINETUNED_TEMPERATURE}
165
- - Max Tokens: {self.FINETUNED_MAX_NEW_TOKENS}
166
- """
167
-
168
 
169
  # ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•œ ๋ณ„์นญ
170
  PreprocessConfig = Config
171
- RAGConfig = Config
172
-
173
-
174
- # ํ…Œ์ŠคํŠธ์šฉ
175
- if __name__ == "__main__":
176
- config = Config()
177
- print(config)
 
18
  self.BASE_FOLDER_PATH = "./data/files/"
19
  self.OUTPUT_CHUNKS_PATH = "./data/rag_chunks_final.csv"
20
 
21
+ # RAG - ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์šฐ์„ , ์—†์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’
22
  self.RAG_INPUT_PATH = "./data/rag_chunks_final.csv"
23
+ self.DB_DIRECTORY = os.getenv("CHROMA_DB_PATH", "./chroma_db")
24
 
25
  # ===== ์ „์ฒ˜๋ฆฌ ์„ค์ • =====
26
  self.CHUNK_SIZE = 1000
27
  self.CHUNK_OVERLAP = 200
28
  self.SEPARATORS = ["\n\n", "\n", " ", ""]
29
+ self.MIN_TEXT_LENGTH = 100
30
 
31
  # ===== ์ž„๋ฒ ๋”ฉ ์„ค์ • =====
32
  self.EMBEDDING_MODEL_NAME = "text-embedding-3-small"
 
42
 
43
  # ===== ๊ฒ€์ƒ‰ ์„ค์ • =====
44
  self.DEFAULT_TOP_K = 10
45
+ self.DEFAULT_ALPHA = 0.5
46
  self.DEFAULT_SEARCH_MODE = "hybrid_rerank"
47
 
48
  # ===== LLM ์„ค์ • =====
49
+ self.LLM_MODEL_NAME = "gpt-4o-mini"
50
  self.DEFAULT_TEMPERATURE = 0.0
51
  self.DEFAULT_MAX_TOKENS = 1000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  # ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ
54
  self.SYSTEM_PROMPT = "๋‹น์‹ ์€ RFP(์ œ์•ˆ์š”์ฒญ์„œ) ๋ถ„์„ ๋ฐ ์š”์•ฝ ์ „๋ฌธ๊ฐ€์ž…๋‹ˆ๋‹ค."
55
 
 
 
 
 
 
 
 
 
56
  def _get_api_key(self) -> str:
57
  """ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ API ํ‚ค ๋กœ๋“œ"""
58
  api_key = os.getenv("OPENAI_API_KEY")
 
77
  f"ํŒŒ์ผ ํด๋”๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: {self.BASE_FOLDER_PATH}"
78
  )
79
 
 
80
  output_dir = os.path.dirname(self.OUTPUT_CHUNKS_PATH)
81
  if output_dir:
82
  os.makedirs(output_dir, exist_ok=True)
 
88
  if not self.OPENAI_API_KEY:
89
  raise ValueError("OPENAI_API_KEY๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค")
90
 
 
 
 
 
 
91
  return True
92
 
93
  def validate_all(self):
 
100
  """์„ค์ • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ (ํ•˜์œ„ ํ˜ธํ™˜์„ฑ)"""
101
  return self.validate_preprocess()
102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  # ํ•˜์œ„ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•œ ๋ณ„์นญ
105
  PreprocessConfig = Config
106
+ RAGConfig = Config
 
 
 
 
 
 
start.sh ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ echo "๐Ÿ”„ ChromaDB ์ดˆ๊ธฐํ™” ์ค‘..."
5
+
6
+ # ์›๋ณธ ChromaDB๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ
7
+ if [ -d "/app/chroma_db" ]; then
8
+ echo "โœ… ์›๋ณธ ChromaDB ๋ฐœ๊ฒฌ: /app/chroma_db"
9
+
10
+ # ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ ์œ„์น˜๋กœ ๋ณต์‚ฌ
11
+ echo "๐Ÿ“ฆ ChromaDB๋ฅผ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•œ ์œ„์น˜๋กœ ๋ณต์‚ฌ ์ค‘..."
12
+ cp -r /app/chroma_db /app/.cache/chroma_db
13
+
14
+ echo "โœ… ChromaDB ๋ณต์‚ฌ ์™„๋ฃŒ: /app/.cache/chroma_db"
15
+ else
16
+ echo "โš ๏ธ ์›๋ณธ ChromaDB๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค: /app/chroma_db"
17
+ exit 1
18
+ fi
19
+
20
+ echo "๐Ÿš€ Streamlit ์•ฑ ์‹œ์ž‘..."
21
+ exec streamlit run src/visualization/chatbot_app.py \
22
+ --server.port=7860 \
23
+ --server.address=0.0.0.0 \
24
+ --server.headless=true \
25
+ --server.fileWatcherType=none