fix: main & yml

This commit is contained in:
KofK 2025-02-15 13:52:05 +03:00
parent 2eafc574b6
commit 3928cbcd61
6 changed files with 141 additions and 76 deletions

17
.gitignore vendored
View File

@ -2,3 +2,20 @@
/__pycache__
/myenv
imageboard.db
**/node_modules
**/venv
**/.git
**/.github
**/logs
**/dist
**/build
*.log
*.md
.DS_Store
.env
**/__pycache__
*.sqlite3
*.pyc
*.pyo
*.pyd
.Python

View File

@ -1,9 +1,22 @@
# Dockerfile
# Используем официальный образ Python
FROM python:3.9-slim
ENV PYTHONUNBUFFERED 1
# Устанавливаем системные зависимости
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc python3-dev && \
rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
python3-dev \
&& rm -rf /var/lib/apt/lists/*
# Рабочая директория
WORKDIR /app
# Сначала копируем только зависимости
COPY requirements.txt .
# Устанавливаем зависимости с кэшированием
RUN pip install --no-cache-dir -r requirements.txt
# Копируем остальные файлы
COPY . .
# Команда для запуска (замените на вашу)
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@ -1,4 +1,4 @@
version: '3.8'
version: "3.8"
services:
qdrant:
@ -10,38 +10,24 @@ services:
volumes:
- qdrant_data:/qdrant/storage
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "--fail", "http://qdrant:6333"]
interval: 30s
timeout: 10s
retries: 3
app:
build: .
backend:
build:
context: .
dockerfile: Dockerfile
container_name: backend
ports:
- "8000:8000"
volumes:
- .:/app
working_dir: /app
depends_on:
qdrant:
condition: service_healthy
command: sh -c "pip install -r requirements.txt && uvicorn main:app --host 0.0.0.0 --port 8000 --reload"
restart: unless-stopped
frontend:
futa-clone:
build:
context: .
dockerfile: ./futa-clone/Dockerfile.frontend
container_name: frontend
context: ./futa-clone
dockerfile: Dockerfile
container_name: futa-clone
ports:
- "3000:3000"
volumes:
- ./futa-clone:/app
working_dir: /app
depends_on:
- qdrant
command: sh -c "npm install && npm run start"
restart: unless-stopped
volumes:
qdrant_data:

18
futa-clone/Dockerfile Normal file
View File

@ -0,0 +1,18 @@
# Используем официальный Node.js образ (на примере версии 16 на базе Alpine)
FROM node:20-alpine
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app
# Копируем файлы зависимостей и устанавливаем их
COPY package*.json ./
RUN npm install
# Копируем исходный код приложения
COPY . .
# Если требуется, можно указать порт (например, 3000)
EXPOSE 3000
# Запускаем приложение
CMD ["npm", "run", "start"]

View File

@ -1,4 +0,0 @@
# Dockerfile.frontend
FROM node:18-alpine
RUN apk add --no-cache git

113
main.py
View File

@ -10,6 +10,7 @@ import requests
from qdrant_client import QdrantClient
from qdrant_client.http import models
from fastapi.middleware.cors import CORSMiddleware
import time # Добавлен импорт модуля time
# Database setup
from sqlalchemy import create_engine, Column, String, DateTime, Text
@ -26,78 +27,112 @@ import logging
from qdrant_client.http.models import VectorParams, Distance
# Настройка базового логирования (например, вывод в консоль)
# Настройка базового логирования
logging.basicConfig(
level=logging.INFO, # Можно изменить уровень, например, на DEBUG
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s - %(message)s"
)
logger = logging.getLogger(__name__)
# Задайте имя коллекции
# Конфигурация
COLLECTION_NAME = "posts"
# Определите размер вектора. Этот размер должен соответствовать длине объединённого эмбеддинга текста и изображения.
VECTOR_SIZE = 1280 # Пример: поменяйте на актуальное значение для вашего случая
# Configuration
VECTOR_SIZE = 1280
DATABASE_URL = "sqlite:///./imageboard.db"
QDRANT_URL = "http://localhost:6333"
OLLAMA_URL = "http://localhost:11434"
EMBEDDING_MODEL = "nomic-embed-text" # Локальная модель через Ollama
IMAGE_MODEL = "openai/clip-vit-base-patch32" # Локальная CLIP модель
EMBEDDING_MODEL = "nomic-embed-text"
IMAGE_MODEL = "openai/clip-vit-base-patch32"
IMAGE_SIZE = (224, 224)
UPLOAD_DIR = "uploads"
os.makedirs(UPLOAD_DIR, exist_ok=True)
# Initialize components
# Инициализация компонентов
Base = declarative_base()
engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
#Base.metadata.drop_all(bind=engine) # Удаляет все таблицы
#Base.metadata.create_all(bind=engine) # Создаёт таблицы заново
# Инициализация CLIP для изображений
# Инициализация CLIP
clip_model = CLIPModel.from_pretrained(IMAGE_MODEL)
clip_processor = CLIPProcessor.from_pretrained(IMAGE_MODEL)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
clip_model = clip_model.to(device)
# Qdrant клиент
qdrant_client = QdrantClient(QDRANT_URL)
# Функция для создания QdrantClient с повторными попытками
def create_qdrant_client():
max_attempts = 5
attempt = 0
while attempt < max_attempts:
try:
client = QdrantClient(QDRANT_URL)
# Проверка подключения
client.get_collections()
logger.info("Успешное подключение к Qdrant")
return client
except Exception as e:
logger.warning(f"Попытка {attempt+1} подключения к Qdrant не удалась: {str(e)}")
attempt += 1
time.sleep(2)
raise RuntimeError(f"Не удалось подключиться к Qdrant после {max_attempts} попыток")
# Инициализация клиента Qdrant
try:
qdrant_client = create_qdrant_client()
except Exception as e:
logger.error(f"Ошибка инициализации Qdrant: {str(e)}")
raise
# Функция проверки и создания коллекции
def ensure_collection_exists():
try:
# Попытка получить коллекцию. Если коллекция не существует, Qdrant выбросит исключение.
qdrant_client.get_collection(collection_name=COLLECTION_NAME)
logger.info("Коллекция '%s' существует.", COLLECTION_NAME)
except Exception as e:
logger.info("Коллекция '%s' не найдена. Создаём коллекцию...", COLLECTION_NAME)
qdrant_client.create_collection(
collection_name=COLLECTION_NAME,
vectors_config=VectorParams(
size=VECTOR_SIZE,
distance=Distance.COSINE # Или другой подходящий тип расстояния
)
)
logger.info("Коллекция '%s' создана.", COLLECTION_NAME)
max_attempts = 5
attempt = 0
while attempt < max_attempts:
try:
# Проверка существования коллекции
qdrant_client.get_collection(collection_name=COLLECTION_NAME)
logger.info(f"Коллекция '{COLLECTION_NAME}' существует")
return
except Exception as e:
if "not found" in str(e).lower():
logger.info(f"Создание коллекции '{COLLECTION_NAME}'...")
try:
qdrant_client.create_collection(
collection_name=COLLECTION_NAME,
vectors_config=VectorParams(
size=VECTOR_SIZE,
distance=Distance.COSINE
)
)
logger.info(f"Коллекция '{COLLECTION_NAME}' создана")
return
except Exception as create_error:
logger.error(f"Ошибка создания: {str(create_error)}")
else:
logger.error(f"Ошибка подключения: {str(e)}")
# Вызываем функцию при инициализации приложения, например, в начале main.py
ensure_collection_exists()
attempt += 1
time.sleep(2)
raise RuntimeError(f"Не удалось инициализировать коллекцию после {max_attempts} попыток")
# Вызов функции проверки коллекции
try:
ensure_collection_exists()
except Exception as e:
logger.error(f"Ошибка инициализации коллекции: {str(e)}")
raise
# Инициализация FastAPI
app = FastAPI()
app.mount("/uploads", StaticFiles(directory=UPLOAD_DIR), name=UPLOAD_DIR)
app.mount("/uploads", StaticFiles(directory=UPLOAD_DIR), name="uploads")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Разрешить все источники
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"], # Разрешить все методы
allow_headers=["*"], # Разрешить все заголовки
allow_methods=["*"],
allow_headers=["*"],
)
# Database models
# Модель базы данных
class Post(Base):
__tablename__ = "posts"
id = Column(String, primary_key=True, index=True)