fix: main & yml
This commit is contained in:
parent
2eafc574b6
commit
3928cbcd61
17
.gitignore
vendored
17
.gitignore
vendored
@ -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
|
25
Dockerfile
25
Dockerfile
@ -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"]
|
@ -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
18
futa-clone/Dockerfile
Normal 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"]
|
@ -1,4 +0,0 @@
|
||||
# Dockerfile.frontend
|
||||
FROM node:18-alpine
|
||||
|
||||
RUN apk add --no-cache git
|
99
main.py
99
main.py
@ -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)
|
||||
|
||||
def ensure_collection_exists():
|
||||
# Функция для создания QdrantClient с повторными попытками
|
||||
def create_qdrant_client():
|
||||
max_attempts = 5
|
||||
attempt = 0
|
||||
while attempt < max_attempts:
|
||||
try:
|
||||
# Попытка получить коллекцию. Если коллекция не существует, Qdrant выбросит исключение.
|
||||
qdrant_client.get_collection(collection_name=COLLECTION_NAME)
|
||||
logger.info("Коллекция '%s' существует.", COLLECTION_NAME)
|
||||
client = QdrantClient(QDRANT_URL)
|
||||
# Проверка подключения
|
||||
client.get_collections()
|
||||
logger.info("Успешное подключение к Qdrant")
|
||||
return client
|
||||
except Exception as e:
|
||||
logger.info("Коллекция '%s' не найдена. Создаём коллекцию...", COLLECTION_NAME)
|
||||
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():
|
||||
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 # Или другой подходящий тип расстояния
|
||||
distance=Distance.COSINE
|
||||
)
|
||||
)
|
||||
logger.info("Коллекция '%s' создана.", COLLECTION_NAME)
|
||||
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
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user