Spaces:
Sleeping
Sleeping
HaRin2806
commited on
Commit
·
ca362fb
1
Parent(s):
8275526
fix bug
Browse files- Dockerfile +9 -16
- core/embedding_model.py +40 -41
Dockerfile
CHANGED
|
@@ -1,15 +1,16 @@
|
|
| 1 |
-
# Sử dụng bookworm thay vì bullseye vì có SQLite3 phiên bản mới hơn
|
| 2 |
FROM python:3.9-slim-bookworm
|
| 3 |
|
| 4 |
-
# Thiết lập working directory
|
| 5 |
WORKDIR /app
|
| 6 |
|
| 7 |
-
# Thiết lập environment variables
|
| 8 |
ENV PYTHONPATH=/app
|
| 9 |
ENV ENVIRONMENT=production
|
| 10 |
ENV PYTHONUNBUFFERED=1
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
-
# Cài đặt system dependencies
|
| 13 |
RUN apt-get update && apt-get install -y \
|
| 14 |
build-essential \
|
| 15 |
gcc \
|
|
@@ -19,23 +20,15 @@ RUN apt-get update && apt-get install -y \
|
|
| 19 |
libsqlite3-dev \
|
| 20 |
&& rm -rf /var/lib/apt/lists/*
|
| 21 |
|
| 22 |
-
#
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
# Cài đặt pysqlite3-binary trước để override SQLite3 nếu cần
|
| 26 |
-
RUN pip install --no-cache-dir pysqlite3-binary
|
| 27 |
|
| 28 |
-
|
| 29 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 30 |
|
| 31 |
-
# Copy source code
|
| 32 |
COPY . .
|
| 33 |
-
|
| 34 |
-
# Tạo thư mục cần thiết
|
| 35 |
RUN mkdir -p logs uploads chroma_data
|
| 36 |
|
| 37 |
-
# Expose port
|
| 38 |
EXPOSE 7860
|
| 39 |
-
|
| 40 |
-
# Chạy ứng dụng
|
| 41 |
CMD ["python", "app.py"]
|
|
|
|
|
|
|
| 1 |
FROM python:3.9-slim-bookworm
|
| 2 |
|
|
|
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
+
# Thiết lập environment variables cho cache
|
| 6 |
ENV PYTHONPATH=/app
|
| 7 |
ENV ENVIRONMENT=production
|
| 8 |
ENV PYTHONUNBUFFERED=1
|
| 9 |
+
ENV HF_HOME=/app/.cache/huggingface
|
| 10 |
+
ENV TRANSFORMERS_CACHE=/app/.cache/transformers
|
| 11 |
+
ENV SENTENCE_TRANSFORMERS_HOME=/app/.cache/sentence-transformers
|
| 12 |
|
| 13 |
+
# Cài đặt system dependencies
|
| 14 |
RUN apt-get update && apt-get install -y \
|
| 15 |
build-essential \
|
| 16 |
gcc \
|
|
|
|
| 20 |
libsqlite3-dev \
|
| 21 |
&& rm -rf /var/lib/apt/lists/*
|
| 22 |
|
| 23 |
+
# Tạo cache directories với permissions đúng
|
| 24 |
+
RUN mkdir -p /app/.cache/huggingface /app/.cache/transformers /app/.cache/sentence-transformers && \
|
| 25 |
+
chmod -R 777 /app/.cache
|
|
|
|
|
|
|
| 26 |
|
| 27 |
+
COPY requirements.txt .
|
| 28 |
RUN pip install --no-cache-dir -r requirements.txt
|
| 29 |
|
|
|
|
| 30 |
COPY . .
|
|
|
|
|
|
|
| 31 |
RUN mkdir -p logs uploads chroma_data
|
| 32 |
|
|
|
|
| 33 |
EXPOSE 7860
|
|
|
|
|
|
|
| 34 |
CMD ["python", "app.py"]
|
core/embedding_model.py
CHANGED
|
@@ -28,9 +28,17 @@ class EmbeddingModel:
|
|
| 28 |
"""Khởi tạo embedding model và ChromaDB client"""
|
| 29 |
logger.info(f"Đang khởi tạo embedding model: {EMBEDDING_MODEL}")
|
| 30 |
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
# Khởi tạo ChromaDB client với persistent storage
|
| 36 |
self.chroma_client = chromadb.PersistentClient(
|
|
@@ -51,12 +59,27 @@ class EmbeddingModel:
|
|
| 51 |
self.collection = self.chroma_client.create_collection(name=COLLECTION_NAME)
|
| 52 |
logger.info(f"Đã tạo collection mới: {COLLECTION_NAME}")
|
| 53 |
|
| 54 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
"""
|
| 56 |
Encode văn bản thành embeddings
|
| 57 |
|
| 58 |
Args:
|
| 59 |
texts (str or list): Văn bản hoặc danh sách văn bản cần encode
|
|
|
|
| 60 |
|
| 61 |
Returns:
|
| 62 |
list: Embeddings vector
|
|
@@ -65,8 +88,11 @@ class EmbeddingModel:
|
|
| 65 |
if isinstance(texts, str):
|
| 66 |
texts = [texts]
|
| 67 |
|
| 68 |
-
|
| 69 |
-
|
|
|
|
|
|
|
|
|
|
| 70 |
|
| 71 |
return embeddings.tolist()
|
| 72 |
|
|
@@ -89,8 +115,8 @@ class EmbeddingModel:
|
|
| 89 |
try:
|
| 90 |
logger.debug(f"Dang tim kiem cho query: {query[:50]}...")
|
| 91 |
|
| 92 |
-
# Encode query thành embedding
|
| 93 |
-
query_embedding = self.encode(query)[0]
|
| 94 |
|
| 95 |
# Tạo where clause cho age filter
|
| 96 |
where_clause = None
|
|
@@ -163,8 +189,8 @@ class EmbeddingModel:
|
|
| 163 |
|
| 164 |
logger.info(f"Đang thêm {len(documents)} documents vào ChromaDB")
|
| 165 |
|
| 166 |
-
# Encode documents thành embeddings
|
| 167 |
-
embeddings = self.encode(documents)
|
| 168 |
|
| 169 |
# Thêm vào collection
|
| 170 |
self.collection.add(
|
|
@@ -181,22 +207,10 @@ class EmbeddingModel:
|
|
| 181 |
logger.error(f"Lỗi thêm documents: {e}")
|
| 182 |
return False
|
| 183 |
|
|
|
|
| 184 |
def index_chunks(self, chunks):
|
| 185 |
"""
|
| 186 |
Index các chunks dữ liệu vào ChromaDB
|
| 187 |
-
|
| 188 |
-
Args:
|
| 189 |
-
chunks (list): Danh sách chunks với format:
|
| 190 |
-
[
|
| 191 |
-
{
|
| 192 |
-
"content": "nội dung văn bản",
|
| 193 |
-
"metadata": {"chapter": "bai1", "age_group": "1-3", ...},
|
| 194 |
-
"id": "unique_id" (optional)
|
| 195 |
-
}
|
| 196 |
-
]
|
| 197 |
-
|
| 198 |
-
Returns:
|
| 199 |
-
bool: True nếu thành công
|
| 200 |
"""
|
| 201 |
try:
|
| 202 |
if not chunks:
|
|
@@ -251,12 +265,7 @@ class EmbeddingModel:
|
|
| 251 |
return False
|
| 252 |
|
| 253 |
def count(self):
|
| 254 |
-
"""
|
| 255 |
-
Đếm số lượng documents trong collection
|
| 256 |
-
|
| 257 |
-
Returns:
|
| 258 |
-
int: Số lượng documents
|
| 259 |
-
"""
|
| 260 |
try:
|
| 261 |
return self.collection.count()
|
| 262 |
except Exception as e:
|
|
@@ -264,12 +273,7 @@ class EmbeddingModel:
|
|
| 264 |
return 0
|
| 265 |
|
| 266 |
def delete_collection(self):
|
| 267 |
-
"""
|
| 268 |
-
Xóa collection hiện tại
|
| 269 |
-
|
| 270 |
-
Returns:
|
| 271 |
-
bool: True nếu thành công
|
| 272 |
-
"""
|
| 273 |
try:
|
| 274 |
logger.warning(f"Đang xóa collection: {COLLECTION_NAME}")
|
| 275 |
self.chroma_client.delete_collection(name=COLLECTION_NAME)
|
|
@@ -285,12 +289,7 @@ class EmbeddingModel:
|
|
| 285 |
return False
|
| 286 |
|
| 287 |
def get_stats(self):
|
| 288 |
-
"""
|
| 289 |
-
Lấy thống kê về collection
|
| 290 |
-
|
| 291 |
-
Returns:
|
| 292 |
-
dict: Thông tin thống kê
|
| 293 |
-
"""
|
| 294 |
try:
|
| 295 |
total_count = self.count()
|
| 296 |
|
|
|
|
| 28 |
"""Khởi tạo embedding model và ChromaDB client"""
|
| 29 |
logger.info(f"Đang khởi tạo embedding model: {EMBEDDING_MODEL}")
|
| 30 |
|
| 31 |
+
try:
|
| 32 |
+
# Khởi tạo sentence transformer với trust_remote_code=True
|
| 33 |
+
self.model = SentenceTransformer(EMBEDDING_MODEL, trust_remote_code=True)
|
| 34 |
+
logger.info("Đã tải sentence transformer model")
|
| 35 |
+
except Exception as e:
|
| 36 |
+
logger.error(f"Lỗi khởi tạo model: {e}")
|
| 37 |
+
# Thử với cache_folder explicit
|
| 38 |
+
import os
|
| 39 |
+
cache_dir = os.getenv('SENTENCE_TRANSFORMERS_HOME', '/app/.cache/sentence-transformers')
|
| 40 |
+
self.model = SentenceTransformer(EMBEDDING_MODEL, cache_folder=cache_dir, trust_remote_code=True)
|
| 41 |
+
logger.info("Đã tải sentence transformer model với cache folder explicit")
|
| 42 |
|
| 43 |
# Khởi tạo ChromaDB client với persistent storage
|
| 44 |
self.chroma_client = chromadb.PersistentClient(
|
|
|
|
| 59 |
self.collection = self.chroma_client.create_collection(name=COLLECTION_NAME)
|
| 60 |
logger.info(f"Đã tạo collection mới: {COLLECTION_NAME}")
|
| 61 |
|
| 62 |
+
def _add_prefix_to_text(self, text, is_query=True):
|
| 63 |
+
"""
|
| 64 |
+
Thêm prefix cho text theo yêu cầu của multilingual-e5-base
|
| 65 |
+
"""
|
| 66 |
+
# Kiểm tra xem text đã có prefix chưa
|
| 67 |
+
if text.startswith(('query:', 'passage:')):
|
| 68 |
+
return text
|
| 69 |
+
|
| 70 |
+
# Thêm prefix phù hợp
|
| 71 |
+
if is_query:
|
| 72 |
+
return f"query: {text}"
|
| 73 |
+
else:
|
| 74 |
+
return f"passage: {text}"
|
| 75 |
+
|
| 76 |
+
def encode(self, texts, is_query=True):
|
| 77 |
"""
|
| 78 |
Encode văn bản thành embeddings
|
| 79 |
|
| 80 |
Args:
|
| 81 |
texts (str or list): Văn bản hoặc danh sách văn bản cần encode
|
| 82 |
+
is_query (bool): True nếu là query, False nếu là passage
|
| 83 |
|
| 84 |
Returns:
|
| 85 |
list: Embeddings vector
|
|
|
|
| 88 |
if isinstance(texts, str):
|
| 89 |
texts = [texts]
|
| 90 |
|
| 91 |
+
# Thêm prefix cho texts
|
| 92 |
+
processed_texts = [self._add_prefix_to_text(text, is_query) for text in texts]
|
| 93 |
+
|
| 94 |
+
logger.debug(f"Đang encode {len(processed_texts)} văn bản")
|
| 95 |
+
embeddings = self.model.encode(processed_texts, show_progress_bar=False, normalize_embeddings=True)
|
| 96 |
|
| 97 |
return embeddings.tolist()
|
| 98 |
|
|
|
|
| 115 |
try:
|
| 116 |
logger.debug(f"Dang tim kiem cho query: {query[:50]}...")
|
| 117 |
|
| 118 |
+
# Encode query thành embedding (với prefix query:)
|
| 119 |
+
query_embedding = self.encode(query, is_query=True)[0]
|
| 120 |
|
| 121 |
# Tạo where clause cho age filter
|
| 122 |
where_clause = None
|
|
|
|
| 189 |
|
| 190 |
logger.info(f"Đang thêm {len(documents)} documents vào ChromaDB")
|
| 191 |
|
| 192 |
+
# Encode documents thành embeddings (với prefix passage:)
|
| 193 |
+
embeddings = self.encode(documents, is_query=False)
|
| 194 |
|
| 195 |
# Thêm vào collection
|
| 196 |
self.collection.add(
|
|
|
|
| 207 |
logger.error(f"Lỗi thêm documents: {e}")
|
| 208 |
return False
|
| 209 |
|
| 210 |
+
# Các phương thức khác giữ nguyên...
|
| 211 |
def index_chunks(self, chunks):
|
| 212 |
"""
|
| 213 |
Index các chunks dữ liệu vào ChromaDB
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
"""
|
| 215 |
try:
|
| 216 |
if not chunks:
|
|
|
|
| 265 |
return False
|
| 266 |
|
| 267 |
def count(self):
|
| 268 |
+
"""Đếm số lượng documents trong collection"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 269 |
try:
|
| 270 |
return self.collection.count()
|
| 271 |
except Exception as e:
|
|
|
|
| 273 |
return 0
|
| 274 |
|
| 275 |
def delete_collection(self):
|
| 276 |
+
"""Xóa collection hiện tại"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 277 |
try:
|
| 278 |
logger.warning(f"Đang xóa collection: {COLLECTION_NAME}")
|
| 279 |
self.chroma_client.delete_collection(name=COLLECTION_NAME)
|
|
|
|
| 289 |
return False
|
| 290 |
|
| 291 |
def get_stats(self):
|
| 292 |
+
"""Lấy thống kê về collection"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 293 |
try:
|
| 294 |
total_count = self.count()
|
| 295 |
|