edit : imagen -> gemini로 변경, bingimg -> 사용불가 , 벡터검색api 이미지저장이아닌 데이터 전송하는 api 추가 , vactor -> vector 오타 수정
This commit is contained in:
@@ -16,6 +16,7 @@ RESTful API Server
|
|||||||
```
|
```
|
||||||
gcloud init
|
gcloud init
|
||||||
gcloud auth application-default login
|
gcloud auth application-default login
|
||||||
|
gcloud config set compute/region asia-east1
|
||||||
```
|
```
|
||||||
https://cloud.google.com/docs/authentication/set-up-adc-local-dev-environment?hl=ko
|
https://cloud.google.com/docs/authentication/set-up-adc-local-dev-environment?hl=ko
|
||||||
|
|
||||||
|
|||||||
28
config.py
28
config.py
@@ -1,8 +1,12 @@
|
|||||||
class Config:
|
class Config:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.set_rel()
|
self.set_fermat()
|
||||||
|
self.use_imagen = True
|
||||||
|
|
||||||
def set_rel(self):
|
def set_fermat(self):
|
||||||
|
"""
|
||||||
|
내부 서버용
|
||||||
|
"""
|
||||||
self.config = 'rel'
|
self.config = 'rel'
|
||||||
self.remote_folder = "/home/fermat/STORAGE/01.Projects/A2TEC/K_EYEWEAR/02.ML_DATA/Image_generator_result"
|
self.remote_folder = "/home/fermat/STORAGE/01.Projects/A2TEC/K_EYEWEAR/02.ML_DATA/Image_generator_result"
|
||||||
self.sftp_host = "192.168.200.230"
|
self.sftp_host = "192.168.200.230"
|
||||||
@@ -11,6 +15,9 @@ class Config:
|
|||||||
self.sftp_pw = "1234"
|
self.sftp_pw = "1234"
|
||||||
|
|
||||||
def set_dev(self):
|
def set_dev(self):
|
||||||
|
"""
|
||||||
|
개발용
|
||||||
|
"""
|
||||||
self.config = 'dev'
|
self.config = 'dev'
|
||||||
self.remote_folder = "/home/fermat/project/FM_TEST_REST_SERVER/result"
|
self.remote_folder = "/home/fermat/project/FM_TEST_REST_SERVER/result"
|
||||||
self.sftp_host = "192.168.200.231"
|
self.sftp_host = "192.168.200.231"
|
||||||
@@ -21,7 +28,22 @@ class Config:
|
|||||||
import os
|
import os
|
||||||
if not os.path.exists(self.remote_folder):
|
if not os.path.exists(self.remote_folder):
|
||||||
os.makedirs(self.remote_folder)
|
os.makedirs(self.remote_folder)
|
||||||
|
|
||||||
|
def set_ict(self):
|
||||||
|
pass
|
||||||
|
# self.config = 'rel'
|
||||||
|
# self.remote_folder = "/home/fermat/STORAGE/01.Projects/A2TEC/K_EYEWEAR/02.ML_DATA/Image_generator_result"
|
||||||
|
# self.sftp_host = "192.168.200.230"
|
||||||
|
# self.sftp_port = 22
|
||||||
|
# self.sftp_id = "fermat"
|
||||||
|
# self.sftp_pw = "1234"
|
||||||
|
|
||||||
|
def toggle_imagen(self):
|
||||||
|
if self.use_imagen:
|
||||||
|
self.use_imagen = False
|
||||||
|
else:
|
||||||
|
self.use_imagen = True
|
||||||
|
|
||||||
rest_config = Config()
|
rest_config = Config()
|
||||||
# rest_config.set_dev()
|
rest_config.set_dev()
|
||||||
|
rest_config.toggle_imagen()
|
||||||
@@ -56,7 +56,7 @@ Implementation
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def get_models(index_type, model_type):
|
def get_models(index_type, model_type):
|
||||||
from vactor_rest.app import models as M
|
from vector_rest.app import models as M
|
||||||
|
|
||||||
model = None
|
model = None
|
||||||
|
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ class BingArtGenerator:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def link_to_img(self, img_links:list):
|
def link_to_img_remote(self, img_links:list):
|
||||||
"""
|
"""
|
||||||
이미지 링크로 이미지 파일 저장
|
이미지 링크로 이미지 파일 원격지에 저장
|
||||||
"""
|
"""
|
||||||
jpeg_index = 1
|
jpeg_index = 1
|
||||||
|
|
||||||
@@ -80,6 +80,20 @@ class BingArtGenerator:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.link_to_img(img_links=image_links)
|
self.link_to_img_remote(img_links=image_links)
|
||||||
return len(image_links)
|
return len(image_links)
|
||||||
|
|
||||||
|
def get_query_image(self,prompt):
|
||||||
|
|
||||||
|
create_time = D.date_file_name()
|
||||||
|
|
||||||
|
image_links = self.get_image_links(prompt,1)
|
||||||
|
|
||||||
|
if image_links == None:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
image = image_links[0]
|
||||||
|
query_path = os.path.join(TEMP_FOLDER,f"query_bingarg_{create_time}.png")
|
||||||
|
urllib.request.urlretrieve(image, query_path)
|
||||||
|
|
||||||
|
return query_path
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import torch
|
||||||
|
import faiss
|
||||||
|
|
||||||
from custom_apps.faiss_imagenet.utils import preprocessing, preprocessing_quary, normalize, get_dataset_list
|
from custom_apps.faiss_imagenet.utils import preprocessing, preprocessing_quary, normalize, get_dataset_list
|
||||||
from custom_apps.faiss_imagenet.const import *
|
from custom_apps.faiss_imagenet.const import *
|
||||||
@@ -15,17 +17,29 @@ def search_idxs(image_path,dataset_bin=DATASET_BIN,index_type="hnsw",search_num=
|
|||||||
|
|
||||||
DIM = 1280
|
DIM = 1280
|
||||||
|
|
||||||
|
# res = faiss.StandardGpuResources()
|
||||||
|
# __res = faiss.StandardGpuResources()
|
||||||
|
|
||||||
|
|
||||||
dataset_fvces, dataset_index = preprocessing(DIM,dataset_bin,index_type)
|
dataset_fvces, dataset_index = preprocessing(DIM,dataset_bin,index_type)
|
||||||
|
|
||||||
org_fvces, org_index = preprocessing_quary(DIM,image_path,index_type)
|
org_fvces, org_index = preprocessing_quary(DIM,image_path,index_type)
|
||||||
|
|
||||||
|
# cpu -> gpu
|
||||||
|
# gpu_idx = faiss.index_cpu_to_gpu_multiple_py([res], 0, dataset_index)
|
||||||
|
# __gpu_idx = faiss.index_cpu_to_gpu_multiple_py([__res], 0, org_index)
|
||||||
|
|
||||||
dists, idxs = dataset_index.search(normalize(org_fvces), search_num)
|
dists, idxs = dataset_index.search(normalize(org_fvces), search_num)
|
||||||
|
|
||||||
# print(dists[0])
|
|
||||||
# print(idxs[0])
|
|
||||||
|
|
||||||
index_image_save(image_path, dists[0], idxs[0])
|
index_image_save(image_path, dists[0], idxs[0])
|
||||||
|
|
||||||
|
# del dataset_fvces, dataset_index, org_fvces, org_index, dists, idxs
|
||||||
|
# del res, __res, gpu_idx, __gpu_idx
|
||||||
|
|
||||||
|
# torch.cuda.empty_cache()
|
||||||
|
# import gc
|
||||||
|
# gc.collect()
|
||||||
|
|
||||||
def index_image_save(query_image_path, dists, idxs):
|
def index_image_save(query_image_path, dists, idxs):
|
||||||
directory_path, file = os.path.split(query_image_path)
|
directory_path, file = os.path.split(query_image_path)
|
||||||
_name, extension = os.path.splitext(file)
|
_name, extension = os.path.splitext(file)
|
||||||
|
|||||||
40
custom_apps/gemini/main.py
Normal file
40
custom_apps/gemini/main.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
from google import genai
|
||||||
|
from google.genai import types
|
||||||
|
from PIL import Image
|
||||||
|
from io import BytesIO
|
||||||
|
|
||||||
|
from main_rest.app.utils.date_utils import D
|
||||||
|
from const import TEMP_FOLDER
|
||||||
|
|
||||||
|
|
||||||
|
def gemini_image(prompt, folder=None):
|
||||||
|
from custom_logger.main_log import main_logger as LOG
|
||||||
|
|
||||||
|
image_path = ''
|
||||||
|
client = genai.Client(api_key="AIzaSyB7tu67y9gOkJkpQtvI5OAYSzUzwv9qwnE")
|
||||||
|
|
||||||
|
response = client.models.generate_content(
|
||||||
|
model="gemini-2.0-flash-preview-image-generation",
|
||||||
|
contents=prompt,
|
||||||
|
config=types.GenerateContentConfig(
|
||||||
|
response_modalities=['TEXT', 'IMAGE']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if folder == None:
|
||||||
|
folder = TEMP_FOLDER
|
||||||
|
|
||||||
|
if not os.path.exists(folder):
|
||||||
|
os.makedirs(folder)
|
||||||
|
|
||||||
|
for part in response.candidates[0].content.parts:
|
||||||
|
if part.inline_data is not None:
|
||||||
|
image = Image.open(BytesIO((part.inline_data.data)))
|
||||||
|
image_path = os.path.join(folder,f"gemini_{D.date_file_name()}_query.png")
|
||||||
|
image.save(image_path)
|
||||||
|
|
||||||
|
LOG.info(f"image generate : {image_path}")
|
||||||
|
time.sleep(2)
|
||||||
|
return image_path
|
||||||
@@ -15,6 +15,7 @@ class ImagenConst:
|
|||||||
project_id = "glasses-imagen"
|
project_id = "glasses-imagen"
|
||||||
location = "asia-east1"
|
location = "asia-east1"
|
||||||
model = "imagen-3.0-generate-001"
|
model = "imagen-3.0-generate-001"
|
||||||
|
# model = "imagen-3.0-fast-generate-001"
|
||||||
|
|
||||||
|
|
||||||
def imagen_generate_image(prompt,download_count=1):
|
def imagen_generate_image(prompt,download_count=1):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class CookieManager:
|
class CookieManager:
|
||||||
|
|
||||||
DEFAULT_COOKIE = "19S_ux18UhHzxHMsY5gTYwqk2YjYahwxssgJyx0AybuAjDa_kZKWFauqMSrtb1a80s89VjmLwKWIGhvpZxLOzkwcMXAuShkgFwGSVlD8ayI7qgQiCabE9-UFByw4QJ_ZSAnOnskn5iPydk4vaZZEayTR--u7-mVglsaANK6rGOQPeu8q-Sa6cjVCUQR9kkjEtz-J4wf2MQ6inXuC41IbCi8QwmZyHkwxOy6U6CqPiREg"
|
DEFAULT_COOKIE = "1dcelksYDmBzN1R2heBkdpHpku-E2Qr8KAA4bToiSqFBtLUDGPMgKXrpc0X_oVhSCzcX3rk3kB8GgwILUNdvrhgO9Zu_BgcpromvlpjUg1jukhL6v3SBE-YOBQqzBC6OanguFOfAAlFJjB7ZJBzoPQzdrKU7L8yMQZZ-BAsfr18M6MnWy1aaEWljSmOA7_fTql5RcjCPNk_FZBeFXolnOIdNfLqGIFWsPKM8nNZVXNSs"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.cookie = self.DEFAULT_COOKIE
|
self.cookie = self.DEFAULT_COOKIE
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ vactor_logger = None
|
|||||||
|
|
||||||
_now = datetime.datetime.now()
|
_now = datetime.datetime.now()
|
||||||
|
|
||||||
LOGGER_NAME = 'vactor'
|
LOGGER_NAME = 'vector'
|
||||||
LOGGER_FILE_NAME = f'{_now.strftime("%Y-%m-%d %H_%M_%S")}_{LOGGER_NAME}.log'
|
LOGGER_FILE_NAME = f'{_now.strftime("%Y-%m-%d %H_%M_%S")}_{LOGGER_NAME}.log'
|
||||||
|
|
||||||
LOGGER_LEVEL = logging.INFO
|
LOGGER_LEVEL = logging.INFO
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ async def lifespan(app: FastAPI):
|
|||||||
# When service starts.
|
# When service starts.
|
||||||
LOG.info(f"REST start (port : {conf().REST_SERVER_PORT})")
|
LOG.info(f"REST start (port : {conf().REST_SERVER_PORT})")
|
||||||
|
|
||||||
|
import os
|
||||||
|
import const
|
||||||
|
if os.path.exists(const.TEMP_FOLDER):
|
||||||
|
for _file in os.scandir(const.TEMP_FOLDER):
|
||||||
|
os.remove(_file)
|
||||||
|
|
||||||
|
LOG.info(f"temp folder clean")
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
# When service is stopped.
|
# When service is stopped.
|
||||||
|
|||||||
@@ -600,31 +600,40 @@ class BingCookieSetReq(BaseModel):
|
|||||||
|
|
||||||
class VactorImageSearchReq(BaseModel):
|
class VactorImageSearchReq(BaseModel):
|
||||||
"""
|
"""
|
||||||
### [Request] vactor image search request
|
### [Request] vector image search request
|
||||||
"""
|
"""
|
||||||
prompt : str = Field(description='프롬프트', example='검은색 안경')
|
prompt : str = Field(description='프롬프트', example='검은색 안경')
|
||||||
indexType : str = Field(IndexType.l2, description='인덱스 타입', example=IndexType.l2)
|
indexType : str = Field(IndexType.l2, description='인덱스 타입', example=IndexType.l2)
|
||||||
searchNum : int = Field(4, description='검색결과 이미지 갯수', example=4)
|
searchNum : int = Field(4, description='검색결과 이미지 갯수', example=4)
|
||||||
|
|
||||||
|
|
||||||
class VactorImageSearchVitReq(BaseModel):
|
class VectorImageSearchVitReq(BaseModel):
|
||||||
"""
|
"""
|
||||||
### [Request] vactor image search vit
|
### [Request] vector image search vit
|
||||||
"""
|
"""
|
||||||
prompt : str = Field(description='프롬프트', example='검은색 안경')
|
prompt : str = Field(description='프롬프트', example='검은색 안경')
|
||||||
modelType : str = Field(VitModelType.l14, description='pretrained model 타입', example=VitModelType.l14)
|
modelType : str = Field(VitModelType.l14, description='pretrained model 타입', example=VitModelType.l14)
|
||||||
indexType : str = Field(VitIndexType.l2, description='인덱스 타입', example=VitIndexType.l2)
|
indexType : str = Field(VitIndexType.l2, description='인덱스 타입', example=VitIndexType.l2)
|
||||||
searchNum : int = Field(4, description='검색결과 이미지 갯수', example=4)
|
searchNum : int = Field(4, description='검색결과 이미지 갯수', example=4)
|
||||||
|
|
||||||
|
|
||||||
class VactorImageSearchVitReportReq(BaseModel):
|
class VectorImageSearchVitDataReq(VectorImageSearchVitReq):
|
||||||
"""
|
"""
|
||||||
### [Request] vactor image search vit request
|
### [Request] vector image search vit data
|
||||||
|
"""
|
||||||
|
querySend: bool = Field(True, description='쿼리 이미지 전송 여부', example=True)
|
||||||
|
|
||||||
|
class VectorImageSearchVitReportReq(BaseModel):
|
||||||
|
"""
|
||||||
|
### [Request] vector image search vit request
|
||||||
"""
|
"""
|
||||||
prompt : str = Field(description='프롬프트', example='검은색 안경')
|
prompt : str = Field(description='프롬프트', example='검은색 안경')
|
||||||
modelType : str = Field(VitModelType.l14, description='pretrained model 타입', example=VitModelType.l14)
|
modelType : str = Field(VitModelType.l14, description='pretrained model 타입', example=VitModelType.l14)
|
||||||
indexType : str = Field(VitIndexType.l2, description='인덱스 타입', example=VitIndexType.l2)
|
indexType : str = Field(VitIndexType.l2, description='인덱스 타입', example=VitIndexType.l2)
|
||||||
|
|
||||||
|
class VectorImageResult(BaseModel):
|
||||||
|
image : str = Field("", description='이미지 데이터', example='')
|
||||||
|
percents: float = Field(0.0, description='percents 값', example='')
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
@@ -672,4 +681,30 @@ class BingCookieSetRes(ResponseBase):
|
|||||||
BingCookieSetRes.result = True
|
BingCookieSetRes.result = True
|
||||||
BingCookieSetRes.error = None
|
BingCookieSetRes.error = None
|
||||||
BingCookieSetRes.currentCookie = current_cookie
|
BingCookieSetRes.currentCookie = current_cookie
|
||||||
return BingCookieSetRes
|
return BingCookieSetRes
|
||||||
|
|
||||||
|
|
||||||
|
class VectorImageSerachDataRes(ResponseBase):
|
||||||
|
"""
|
||||||
|
### vector image data response
|
||||||
|
"""
|
||||||
|
queryImage : str = Field("", description='쿼리 이미지', example="")
|
||||||
|
vectorResult : List[VectorImageResult] = Field([], description='벡터 검색 결과', example=[])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_error(error,vector_result=[],query_img=""):
|
||||||
|
ImageGenerateRes.result = False
|
||||||
|
ImageGenerateRes.error = str(error)
|
||||||
|
ImageGenerateRes.vectorResult = vector_result
|
||||||
|
ImageGenerateRes.queryImage = query_img
|
||||||
|
|
||||||
|
return ImageGenerateRes
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def set_message(vector_result,query_img=""):
|
||||||
|
ImageGenerateRes.result = True
|
||||||
|
ImageGenerateRes.error = None
|
||||||
|
ImageGenerateRes.vectorResult = vector_result
|
||||||
|
ImageGenerateRes.queryImage = query_img
|
||||||
|
|
||||||
|
return ImageGenerateRes
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
@brief: services api
|
@brief: services api
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import requests, json, traceback, os
|
import requests, json, traceback, os, shutil
|
||||||
from fastapi import APIRouter, Depends, Body
|
from fastapi import APIRouter, Depends, Body
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
from typing import Annotated, List
|
from typing import Annotated, List
|
||||||
@@ -17,109 +17,111 @@ from typing import Annotated, List
|
|||||||
from main_rest.app.common import consts
|
from main_rest.app.common import consts
|
||||||
from main_rest.app import models as M
|
from main_rest.app import models as M
|
||||||
from main_rest.app.utils.date_utils import D
|
from main_rest.app.utils.date_utils import D
|
||||||
|
from main_rest.app.utils.parsing_utils import image_to_base64_string
|
||||||
from custom_logger.main_log import main_logger as LOG
|
from custom_logger.main_log import main_logger as LOG
|
||||||
|
|
||||||
from custom_apps.bingimagecreator.utils import DallEArgument,dalle3_generate_image
|
from custom_apps.bingimagecreator.utils import DallEArgument,dalle3_generate_image
|
||||||
from custom_apps.bingart.bingart import BingArtGenerator
|
from custom_apps.bingart.bingart import BingArtGenerator
|
||||||
from custom_apps.imagen.custom_imagen import imagen_generate_image, imagen_generate_image_path, imagen_generate_temp_image_path
|
from custom_apps.imagen.custom_imagen import imagen_generate_image, imagen_generate_image_path, imagen_generate_temp_image_path
|
||||||
from main_rest.app.utils.parsing_utils import download_range
|
|
||||||
from custom_apps.utils import cookie_manager
|
from custom_apps.utils import cookie_manager
|
||||||
|
from custom_apps.gemini.main import gemini_image
|
||||||
|
from main_rest.app.utils.parsing_utils import download_range
|
||||||
from utils.custom_sftp import sftp_client
|
from utils.custom_sftp import sftp_client
|
||||||
from config import rest_config
|
from config import rest_config
|
||||||
|
from const import TEMP_FOLDER
|
||||||
|
|
||||||
router = APIRouter(prefix="/services")
|
router = APIRouter(prefix="/services")
|
||||||
|
|
||||||
@router.post("/bing/cookie/set", summary="bing 관련 쿠키 set", response_model=M.BingCookieSetRes)
|
# @router.post("/bing/cookie/set", summary="bing 관련 쿠키 set", response_model=M.BingCookieSetRes)
|
||||||
async def bing_cookie_set(request: Request, request_body_info: M.BingCookieSetReq):
|
# async def bing_cookie_set(request: Request, request_body_info: M.BingCookieSetReq):
|
||||||
"""
|
# """
|
||||||
## Bing cookie set
|
# ## Bing cookie set
|
||||||
> 쿠키정보 set
|
# > 쿠키정보 set
|
||||||
|
|
||||||
## 정보
|
# ## 정보
|
||||||
> cookie 값이 빈 값일경우 쿠키정보를 set 하지 않고 현재 쿠키값 return 함
|
# > cookie 값이 빈 값일경우 쿠키정보를 set 하지 않고 현재 쿠키값 return 함
|
||||||
> cookie 값이 정상 쿠키 인지는 확인안함
|
# > cookie 값이 정상 쿠키 인지는 확인안함
|
||||||
|
|
||||||
"""
|
# """
|
||||||
response = M.BingCookieSetRes()
|
# response = M.BingCookieSetRes()
|
||||||
try:
|
# try:
|
||||||
if len(request_body_info.cookie) == 0:
|
# if len(request_body_info.cookie) == 0:
|
||||||
pass
|
# pass
|
||||||
else:
|
# else:
|
||||||
cookie_manager.set_cookie(request_body_info.cookie)
|
# cookie_manager.set_cookie(request_body_info.cookie)
|
||||||
|
|
||||||
return response.set_message(current_cookie=cookie_manager.get_cookie())
|
# return response.set_message(current_cookie=cookie_manager.get_cookie())
|
||||||
|
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
LOG.error(traceback.format_exc())
|
# LOG.error(traceback.format_exc())
|
||||||
return response.set_error(e,current_cookie=cookie_manager.get_cookie())
|
# return response.set_error(e,current_cookie=cookie_manager.get_cookie())
|
||||||
|
|
||||||
|
|
||||||
@router.post("/imageGenerate/bingimg", summary="이미지 생성(AI) - bing image generator (DALL-E 3)", response_model=M.ImageGenerateRes)
|
# @router.post("/imageGenerate/bingimg", summary="이미지 생성(AI) - bing image generator (DALL-E 3)", response_model=M.ImageGenerateRes)
|
||||||
async def bing_img_generate(request: Request, request_body_info: M.ImageGenerateReq):
|
# async def bing_img_generate(request: Request, request_body_info: M.ImageGenerateReq):
|
||||||
"""
|
# """
|
||||||
## 이미지 생성(AI) - bing image generator (DALL-E 3)
|
# ## 이미지 생성(AI) - bing image generator (DALL-E 3)
|
||||||
> bing image generator를 이용하여 이미지 생성
|
# > bing image generator를 이용하여 이미지 생성
|
||||||
|
|
||||||
### Requriements
|
# ### Requriements
|
||||||
|
|
||||||
|
|
||||||
## 정보
|
# ## 정보
|
||||||
> 오류 발생시 오류 발생한 파일은 에러 메세지에만 남기고 저장은 안함
|
# > 오류 발생시 오류 발생한 파일은 에러 메세지에만 남기고 저장은 안함
|
||||||
> *동작 안함.
|
|
||||||
|
|
||||||
"""
|
# """
|
||||||
response = M.ImageGenerateRes()
|
# response = M.ImageGenerateRes()
|
||||||
try:
|
# try:
|
||||||
if not download_range(request_body_info.downloadCount):
|
# if not download_range(request_body_info.downloadCount):
|
||||||
raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
# raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
||||||
|
|
||||||
|
|
||||||
args = DallEArgument(
|
# args = DallEArgument(
|
||||||
prompt=request_body_info.prompt,
|
# prompt=request_body_info.prompt,
|
||||||
download_count=request_body_info.downloadCount
|
# download_count=request_body_info.downloadCount
|
||||||
)
|
# )
|
||||||
|
|
||||||
info = dalle3_generate_image(args)
|
# info = dalle3_generate_image(args)
|
||||||
|
|
||||||
if info.get_error_messages():
|
# if info.get_error_messages():
|
||||||
error_message = f"파일생성 error: {info.get_error_messages()}"
|
# error_message = f"파일생성 error: {info.get_error_messages()}"
|
||||||
LOG.error(error_message)
|
# LOG.error(error_message)
|
||||||
return response.set_error(error=error_message, img_len=info.get_counter())
|
# return response.set_error(error=error_message, img_len=info.get_counter())
|
||||||
|
|
||||||
return response.set_message(img_len=info.get_counter())
|
# return response.set_message(img_len=info.get_counter())
|
||||||
|
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
LOG.error(traceback.format_exc())
|
# LOG.error(traceback.format_exc())
|
||||||
return response.set_error(e)
|
# return response.set_error(e)
|
||||||
|
|
||||||
@router.post("/imageGenerate/bingart", summary="이미지 생성(AI) - bing art (DALL-E 3)", response_model=M.ImageGenerateRes)
|
# @router.post("/imageGenerate/bingart", summary="이미지 생성(AI) - bing art (DALL-E 3)", response_model=M.ImageGenerateRes)
|
||||||
async def bing_art(request: Request, request_body_info: M.ImageGenerateReq):
|
# async def bing_art(request: Request, request_body_info: M.ImageGenerateReq):
|
||||||
"""
|
# """
|
||||||
## 이미지 생성(AI) - bing art (DALL-E 3)
|
# ## 이미지 생성(AI) - bing art (DALL-E 3)
|
||||||
> bing art를 이용하여 이미지 생성
|
# > bing art를 이용하여 이미지 생성
|
||||||
|
|
||||||
### Requriements
|
# ### Requriements
|
||||||
|
|
||||||
|
|
||||||
## 정보
|
# ## 정보
|
||||||
> 오류 발생시 오류 발생한 파일은 에러 메세지에만 남기고 저장은 안함
|
# > 오류 발생시 오류 발생한 파일은 에러 메세지에만 남기고 저장은 안함
|
||||||
> *동작 안함.
|
# > *동작 안함.
|
||||||
|
|
||||||
"""
|
# """
|
||||||
response = M.ImageGenerateRes()
|
# response = M.ImageGenerateRes()
|
||||||
try:
|
# try:
|
||||||
if not download_range(request_body_info.downloadCount):
|
# if not download_range(request_body_info.downloadCount):
|
||||||
raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
# raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
||||||
|
|
||||||
bing_art = BingArtGenerator()
|
# bing_art = BingArtGenerator()
|
||||||
|
|
||||||
info = bing_art.get_images(prompt=request_body_info.prompt,image_len=request_body_info.downloadCount)
|
# info = bing_art.get_images(prompt=request_body_info.prompt,image_len=request_body_info.downloadCount)
|
||||||
|
|
||||||
return response.set_message(img_len=info)
|
# return response.set_message(img_len=info)
|
||||||
|
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
LOG.error(traceback.format_exc())
|
# LOG.error(traceback.format_exc())
|
||||||
return response.set_error(e)
|
# return response.set_error(e)
|
||||||
|
|
||||||
@router.post("/imageGenerate/imagen", summary="이미지 생성(AI) - imagen", response_model=M.ImageGenerateRes)
|
@router.post("/imageGenerate/imagen", summary="이미지 생성(AI) - imagen", response_model=M.ImageGenerateRes)
|
||||||
async def imagen(request: Request, request_body_info: M.ImageGenerateReq):
|
async def imagen(request: Request, request_body_info: M.ImageGenerateReq):
|
||||||
@@ -127,78 +129,102 @@ async def imagen(request: Request, request_body_info: M.ImageGenerateReq):
|
|||||||
## 이미지 생성(AI) - imagen
|
## 이미지 생성(AI) - imagen
|
||||||
> imagen AI를 이용하여 이미지 생성
|
> imagen AI를 이용하여 이미지 생성
|
||||||
|
|
||||||
### Requriements
|
|
||||||
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
|
||||||
> - const.py 에 지정한 OUTPUT_FOLDER 하위에 imagen 폴더가 있어야함.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# imagen 사용중단 gemini로 변경
|
||||||
|
|
||||||
response = M.ImageGenerateRes()
|
response = M.ImageGenerateRes()
|
||||||
try:
|
try:
|
||||||
|
|
||||||
if not download_range(request_body_info.downloadCount):
|
if not download_range(request_body_info.downloadCount):
|
||||||
raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
||||||
|
|
||||||
img_length = imagen_generate_image(prompt=request_body_info.prompt,
|
# NOTE(JWKIM) : imagen 사용 중단
|
||||||
download_count=request_body_info.downloadCount
|
# img_length = imagen_generate_image(prompt=request_body_info.prompt,
|
||||||
)
|
# download_count=request_body_info.downloadCount
|
||||||
|
# )
|
||||||
|
temp_image_path = gemini_image(request_body_info.prompt)
|
||||||
|
_remote_folder = os.path.join(rest_config.remote_folder,"imagen")
|
||||||
|
|
||||||
|
# remote save
|
||||||
|
sftp_client.remote_copy_data(
|
||||||
|
temp_image_path,
|
||||||
|
os.path.join(_remote_folder,f"imagen_{request_body_info.prompt}_{1}_{D.date_file_name()}.png"))
|
||||||
|
|
||||||
return response.set_message(img_len=img_length)
|
# Clean up temporary files
|
||||||
|
if 'temp_image_path' in locals():
|
||||||
|
if os.path.exists(temp_image_path):
|
||||||
|
os.remove(temp_image_path)
|
||||||
|
del temp_image_path
|
||||||
|
|
||||||
|
return response.set_message(img_len=1)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error(traceback.format_exc())
|
LOG.error(traceback.format_exc())
|
||||||
|
|
||||||
|
# Clean up temporary files
|
||||||
|
if 'query_image_path' in locals():
|
||||||
|
if os.path.exists(query_image_path):
|
||||||
|
os.remove(query_image_path)
|
||||||
|
del query_image_path
|
||||||
|
|
||||||
return response.set_error(error=e)
|
return response.set_error(error=e)
|
||||||
|
|
||||||
@router.post("/vactorImageSearch/imagenet/imageGenerate/imagen", summary="벡터 이미지 검색(imagenet) - imagen", response_model=M.ResponseBase)
|
# @router.post("/vactorImageSearch/imagenet/imageGenerate/imagen", summary="벡터 이미지 검색(imagenet) - imagen", response_model=M.ResponseBase)
|
||||||
async def vactor_imagenet(request: Request, request_body_info: M.VactorImageSearchReq):
|
# async def vactor_imagenet(request: Request, request_body_info: M.VactorImageSearchReq):
|
||||||
"""
|
# """
|
||||||
## 벡터 이미지 검색 - imagen
|
# ## 벡터 이미지 검색 - imagen
|
||||||
> imagen AI를 이용하여 이미지 생성 후 vactor 검색
|
# > imagen AI를 이용하여 이미지 생성 후 vector 검색
|
||||||
|
|
||||||
### Requriements
|
# ### Requriements
|
||||||
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
# > - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
||||||
> - const.py 에 지정한 OUTPUT_FOLDER 하위에 imagen 폴더가 있어야함.
|
# > - const.py 에 지정한 OUTPUT_FOLDER 하위에 imagen 폴더가 있어야함.
|
||||||
|
|
||||||
"""
|
# """
|
||||||
response = M.ResponseBase()
|
# # NOTE(JWKIM) : GPU 메모리 이슈로 사용 중단
|
||||||
try:
|
# response = M.ResponseBase()
|
||||||
if request_body_info.indexType not in [M.IndexType.hnsw, M.IndexType.l2]:
|
# try:
|
||||||
raise Exception(f"indexType is hnsw or l2 (current value = {request_body_info.indexType})")
|
# if request_body_info.indexType not in [M.IndexType.hnsw, M.IndexType.l2]:
|
||||||
|
# raise Exception(f"indexType is hnsw or l2 (current value = {request_body_info.indexType})")
|
||||||
|
|
||||||
img_path = imagen_generate_image_path(image_prompt=request_body_info.prompt)
|
# _temp_folder = f"{request_body_info.prompt}_{D.date_file_name()}"
|
||||||
|
|
||||||
vactor_request_data = {'query_image_path' : img_path,
|
# # img_path = imagen_generate_image_path(image_prompt=request_body_info.prompt) #imagen
|
||||||
'index_type' : request_body_info.indexType,
|
# img_path = gemini_image(request_body_info.prompt, os.path.join(TEMP_FOLDER, _temp_folder)) #gemini
|
||||||
'search_num' : request_body_info.searchNum}
|
|
||||||
vactor_response = requests.post('http://localhost:51002/api/services/faiss/vactor/search/imagenet', data=json.dumps(vactor_request_data))
|
|
||||||
|
|
||||||
if vactor_response.status_code != 200:
|
# vector_request_data = {'query_image_path' : img_path,
|
||||||
raise Exception(f"response error: {json.loads(vactor_response.text)['error']}")
|
# 'index_type' : request_body_info.indexType,
|
||||||
|
# 'search_num' : request_body_info.searchNum}
|
||||||
|
# vector_response = requests.post('http://localhost:51002/api/services/faiss/vector/search/imagenet', data=json.dumps(vector_request_data))
|
||||||
|
|
||||||
if json.loads(vactor_response.text)["error"] != None:
|
# if vector_response.status_code != 200:
|
||||||
raise Exception(f"vactor error: {json.loads(vactor_response.text)['error']}")
|
# raise Exception(f"response error: {json.loads(vector_response.text)['error']}")
|
||||||
|
|
||||||
# remote
|
# if json.loads(vector_response.text)["error"] != None:
|
||||||
_directory_path, _file = os.path.split(img_path)
|
# raise Exception(f"vector error: {json.loads(vector_response.text)['error']}")
|
||||||
_base_bame = os.path.basename(_directory_path)
|
|
||||||
|
|
||||||
# remote 폴더 생성
|
# # remote
|
||||||
sftp_client.remote_mkdir(os.path.join(rest_config.remote_folder, _base_bame))
|
# _directory_path, _file = os.path.split(img_path)
|
||||||
|
|
||||||
# remote 폴더에 이미지 저장
|
# # remote 폴더 생성
|
||||||
for i in os.listdir(_directory_path):
|
# sftp_client.remote_mkdir(os.path.join(rest_config.remote_folder, _temp_folder))
|
||||||
sftp_client.remote_copy_data(local_path=os.path.join(_directory_path, i), remote_path=os.path.join(rest_config.remote_folder, _base_bame, i))
|
|
||||||
|
|
||||||
return response.set_message()
|
# # remote 폴더에 이미지 저장
|
||||||
|
# for i in os.listdir(_directory_path):
|
||||||
|
# sftp_client.remote_copy_data(local_path=os.path.join(_directory_path, i),
|
||||||
|
# remote_path=os.path.join(rest_config.remote_folder, _temp_folder, i))
|
||||||
|
# shutil.rmtree(_directory_path)
|
||||||
|
# return response.set_message()
|
||||||
|
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
LOG.error(traceback.format_exc())
|
# LOG.error(traceback.format_exc())
|
||||||
return response.set_error(error=e)
|
# return response.set_error(error=e)
|
||||||
|
|
||||||
@router.post("/vactorImageSearch/vit/imageGenerate/imagen", summary="벡터 이미지 검색(clip-vit) - imagen", response_model=M.ResponseBase)
|
@router.post("/vactorImageSearch/vit/imageGenerate/imagen", summary="벡터 이미지 검색(clip-vit) - imagen", response_model=M.ResponseBase)
|
||||||
async def vactor_vit_report(request: Request, request_body_info: M.VactorImageSearchVitReq):
|
async def vactor_vit(request: Request, request_body_info: M.VectorImageSearchVitReq):
|
||||||
"""
|
"""
|
||||||
## 벡터 이미지 검색(clip-vit) - imagen
|
## 벡터 이미지 검색(clip-vit) - imagen
|
||||||
> imagen AI를 이용하여 이미지 생성 후 vactor 검색 그후 결과 이미지 생성
|
> imagen AI를 이용하여 이미지 생성 후 vector 검색 그후 결과 이미지 생성
|
||||||
|
|
||||||
### Requriements
|
### Requriements
|
||||||
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
||||||
@@ -219,14 +245,15 @@ async def vactor_vit_report(request: Request, request_body_info: M.VactorImageSe
|
|||||||
if request_body_info.indexType not in [M.VitIndexType.cos, M.VitIndexType.l2]:
|
if request_body_info.indexType not in [M.VitIndexType.cos, M.VitIndexType.l2]:
|
||||||
raise Exception(f"indexType is invalid (current value = {request_body_info.indexType})")
|
raise Exception(f"indexType is invalid (current value = {request_body_info.indexType})")
|
||||||
|
|
||||||
query_image_path = imagen_generate_temp_image_path(image_prompt=request_body_info.prompt)
|
# query_image_path = imagen_generate_temp_image_path(image_prompt=request_body_info.prompt) #imagen
|
||||||
|
query_image_path = gemini_image(request_body_info.prompt) #gemini
|
||||||
|
|
||||||
vector_request_data = {'query_image_path' : query_image_path,
|
vector_request_data = {'query_image_path' : query_image_path,
|
||||||
'index_type' : request_body_info.indexType,
|
'index_type' : request_body_info.indexType,
|
||||||
'model_type' : request_body_info.modelType,
|
'model_type' : request_body_info.modelType,
|
||||||
'search_num' : request_body_info.searchNum}
|
'search_num' : request_body_info.searchNum}
|
||||||
|
|
||||||
vector_response = requests.post('http://localhost:51002/api/services/faiss/vactor/search/vit', data=json.dumps(vector_request_data))
|
vector_response = requests.post('http://localhost:51002/api/services/faiss/vector/search/vit', data=json.dumps(vector_request_data))
|
||||||
|
|
||||||
vector_response_dict = json.loads(vector_response.text)
|
vector_response_dict = json.loads(vector_response.text)
|
||||||
|
|
||||||
@@ -234,7 +261,7 @@ async def vactor_vit_report(request: Request, request_body_info: M.VactorImageSe
|
|||||||
raise Exception(f"response error: {vector_response_dict['error']}")
|
raise Exception(f"response error: {vector_response_dict['error']}")
|
||||||
|
|
||||||
if vector_response_dict["error"] != None:
|
if vector_response_dict["error"] != None:
|
||||||
raise Exception(f"vactor error: {vector_response_dict['error']}")
|
raise Exception(f"vector error: {vector_response_dict['error']}")
|
||||||
|
|
||||||
result_image_paths = vector_response_dict.get('img_list').get('result_image_paths')
|
result_image_paths = vector_response_dict.get('img_list').get('result_image_paths')
|
||||||
result_percents = vector_response_dict.get('img_list').get('result_percents')
|
result_percents = vector_response_dict.get('img_list').get('result_percents')
|
||||||
@@ -267,12 +294,92 @@ async def vactor_vit_report(request: Request, request_body_info: M.VactorImageSe
|
|||||||
del query_image_path
|
del query_image_path
|
||||||
|
|
||||||
return response.set_error(error=e)
|
return response.set_error(error=e)
|
||||||
|
|
||||||
|
@router.post("/vactorImageSearch/vit/imageGenerate/imagen/data", summary="벡터 이미지 검색(clip-vit) - imagen(data)", response_model=M.VectorImageSerachDataRes)
|
||||||
|
async def vactor_vit_report_data(request: Request, request_body_info: M.VectorImageSearchVitDataReq):
|
||||||
|
"""
|
||||||
|
## 벡터 이미지 검색(clip-vit) - imagen
|
||||||
|
> imagen AI를 이용하여 이미지 생성 후 vector 검색 그후 결과 이미지데이터 return
|
||||||
|
|
||||||
|
### Requriements
|
||||||
|
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
||||||
|
|
||||||
|
### options
|
||||||
|
> - modelType -> b32,b16,l14,l14_336
|
||||||
|
> - indexType -> l2,cos
|
||||||
|
|
||||||
|
"""
|
||||||
|
response = M.VectorImageSerachDataRes()
|
||||||
|
query_image_data = ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not download_range(request_body_info.searchNum, max=10):
|
||||||
|
raise Exception(f"downloadCound is invalid (current value = {request_body_info.searchNum})")
|
||||||
|
|
||||||
|
if request_body_info.modelType not in [M.VitModelType.b32, M.VitModelType.b16, M.VitModelType.l14, M.VitModelType.l14_336]:
|
||||||
|
raise Exception(f"modelType is invalid (current value = {request_body_info.modelType})")
|
||||||
|
|
||||||
|
if request_body_info.indexType not in [M.VitIndexType.cos, M.VitIndexType.l2]:
|
||||||
|
raise Exception(f"indexType is invalid (current value = {request_body_info.indexType})")
|
||||||
|
|
||||||
|
# query_image_path = imagen_generate_temp_image_path(image_prompt=request_body_info.prompt) #imagen
|
||||||
|
query_image_path = gemini_image(request_body_info.prompt) #gemini
|
||||||
|
|
||||||
|
vector_request_data = {'query_image_path' : query_image_path,
|
||||||
|
'index_type' : request_body_info.indexType,
|
||||||
|
'model_type' : request_body_info.modelType,
|
||||||
|
'search_num' : request_body_info.searchNum}
|
||||||
|
|
||||||
|
vector_response = requests.post('http://localhost:51002/api/services/faiss/vector/search/vit', data=json.dumps(vector_request_data))
|
||||||
|
|
||||||
|
vector_response_dict = json.loads(vector_response.text)
|
||||||
|
|
||||||
|
if vector_response.status_code != 200:
|
||||||
|
raise Exception(f"response error: {vector_response_dict['error']}")
|
||||||
|
|
||||||
|
if vector_response_dict["error"] != None:
|
||||||
|
raise Exception(f"vector error: {vector_response_dict['error']}")
|
||||||
|
|
||||||
|
result_image_paths = vector_response_dict.get('img_list').get('result_image_paths')
|
||||||
|
result_percents = vector_response_dict.get('img_list').get('result_percents')
|
||||||
|
|
||||||
|
# 이미지 데이터 생성
|
||||||
|
vector_image_results = []
|
||||||
|
for img, percents in zip(result_image_paths, result_percents):
|
||||||
|
b64_data = image_to_base64_string(img)
|
||||||
|
float_percent = float(percents)
|
||||||
|
|
||||||
|
info = M.VectorImageResult(image=b64_data,percents=float_percent)
|
||||||
|
|
||||||
|
vector_image_results.append(info)
|
||||||
|
|
||||||
|
if request_body_info.querySend:
|
||||||
|
query_image_data = image_to_base64_string(query_image_path)
|
||||||
|
|
||||||
|
# Clean up temporary files
|
||||||
|
if 'query_image_path' in locals():
|
||||||
|
if os.path.exists(query_image_path):
|
||||||
|
os.remove(query_image_path)
|
||||||
|
del query_image_path
|
||||||
|
|
||||||
|
return response.set_message(vector_result=vector_image_results,query_img=query_image_data)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
LOG.error(traceback.format_exc())
|
||||||
|
|
||||||
|
# Clean up temporary files
|
||||||
|
if 'query_image_path' in locals():
|
||||||
|
if os.path.exists(query_image_path):
|
||||||
|
os.remove(query_image_path)
|
||||||
|
del query_image_path
|
||||||
|
|
||||||
|
return response.set_error(error=e)
|
||||||
|
|
||||||
@router.post("/vactorImageSearch/vit/imageGenerate/imagen/report", summary="벡터 이미지 검색(clip-vit) - imagen, report 생성", response_model=M.ResponseBase)
|
@router.post("/vactorImageSearch/vit/imageGenerate/imagen/report", summary="벡터 이미지 검색(clip-vit) - imagen, report 생성", response_model=M.ResponseBase)
|
||||||
async def vactor_vit_report(request: Request, request_body_info: M.VactorImageSearchVitReportReq):
|
async def vactor_vit_report(request: Request, request_body_info: M.VectorImageSearchVitReportReq):
|
||||||
"""
|
"""
|
||||||
## 벡터 이미지 검색(clip-vit) - imagen, report 생성
|
## 벡터 이미지 검색(clip-vit) - imagen, report 생성
|
||||||
> imagen AI를 이용하여 이미지 생성 후 vactor 검색 그후 종합결과 이미지 생성
|
> imagen AI를 이용하여 이미지 생성 후 vector 검색 그후 종합결과 이미지 생성
|
||||||
|
|
||||||
### Requriements
|
### Requriements
|
||||||
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
||||||
@@ -290,7 +397,8 @@ async def vactor_vit_report(request: Request, request_body_info: M.VactorImageSe
|
|||||||
if request_body_info.indexType not in [M.VitIndexType.cos, M.VitIndexType.l2]:
|
if request_body_info.indexType not in [M.VitIndexType.cos, M.VitIndexType.l2]:
|
||||||
raise Exception(f"indexType is invalid (current value = {request_body_info.indexType})")
|
raise Exception(f"indexType is invalid (current value = {request_body_info.indexType})")
|
||||||
|
|
||||||
query_image_path = imagen_generate_temp_image_path(image_prompt=request_body_info.prompt)
|
# query_image_path = imagen_generate_temp_image_path(image_prompt=request_body_info.prompt) #imagen
|
||||||
|
query_image_path = gemini_image(request_body_info.prompt) #gemini
|
||||||
report_image_path = f"{os.path.splitext(query_image_path)[0]}_report.png"
|
report_image_path = f"{os.path.splitext(query_image_path)[0]}_report.png"
|
||||||
|
|
||||||
vactor_request_data = {'query_image_path' : query_image_path,
|
vactor_request_data = {'query_image_path' : query_image_path,
|
||||||
@@ -298,13 +406,13 @@ async def vactor_vit_report(request: Request, request_body_info: M.VactorImageSe
|
|||||||
'model_type' : request_body_info.modelType,
|
'model_type' : request_body_info.modelType,
|
||||||
'report_path' : report_image_path}
|
'report_path' : report_image_path}
|
||||||
|
|
||||||
vactor_response = requests.post('http://localhost:51002/api/services/faiss/vactor/search/vit/report', data=json.dumps(vactor_request_data))
|
vactor_response = requests.post('http://localhost:51002/api/services/faiss/vector/search/vit/report', data=json.dumps(vactor_request_data))
|
||||||
|
|
||||||
if vactor_response.status_code != 200:
|
if vactor_response.status_code != 200:
|
||||||
raise Exception(f"response error: {json.loads(vactor_response.text)['error']}")
|
raise Exception(f"response error: {json.loads(vactor_response.text)['error']}")
|
||||||
|
|
||||||
if json.loads(vactor_response.text)["error"] != None:
|
if json.loads(vactor_response.text)["error"] != None:
|
||||||
raise Exception(f"vactor error: {json.loads(vactor_response.text)['error']}")
|
raise Exception(f"vector error: {json.loads(vactor_response.text)['error']}")
|
||||||
|
|
||||||
# remote 폴더에 이미지 저장
|
# remote 폴더에 이미지 저장
|
||||||
sftp_client.remote_copy_data(local_path=report_image_path,
|
sftp_client.remote_copy_data(local_path=report_image_path,
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
import os
|
||||||
|
import base64
|
||||||
|
|
||||||
from const import ILLEGAL_FILE_NAME
|
from const import ILLEGAL_FILE_NAME
|
||||||
|
|
||||||
|
|
||||||
def prompt_to_filenames(prompt):
|
def prompt_to_filenames(prompt):
|
||||||
"""
|
"""
|
||||||
prompt 에 사용할 수 없는 문자가 있으면 '_' 로 치환
|
prompt 에 사용할 수 없는 문자가 있으면 '_' 로 치환
|
||||||
@@ -22,4 +26,36 @@ def download_range(download_count:int,max=4):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def image_to_base64_string(image_path: str) -> str:
|
||||||
|
"""
|
||||||
|
이미지 파일 경로를 입력받아 해당 이미지를 Base64 문자열로 인코딩하여 반환합니다.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
image_path (str): Base64로 변환할 이미지 파일의 경로 (예: "path/to/your/image.png").
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 인코딩된 Base64 문자열. 이미지 파일을 찾을 수 없거나 읽을 수 없는 경우 빈 문자열을 반환합니다.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: 지정된 이미지 경로에 파일이 존재하지 않을 때 발생합니다.
|
||||||
|
IOError: 파일을 읽는 도중 오류가 발생할 때 발생합니다.
|
||||||
|
"""
|
||||||
|
if not os.path.exists(image_path):
|
||||||
|
raise FileNotFoundError(f"Image file not found at: {image_path}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(image_path, "rb") as image_file:
|
||||||
|
# 이미지 파일을 이진(binary) 모드로 읽습니다.
|
||||||
|
binary_data = image_file.read()
|
||||||
|
# 이진 데이터를 Base64로 인코딩합니다.
|
||||||
|
base64_encoded_data = base64.b64encode(binary_data)
|
||||||
|
# 바이트 문자열을 UTF-8 디코딩하여 일반 문자열로 반환합니다.
|
||||||
|
base64_string = base64_encoded_data.decode('utf-8')
|
||||||
|
return base64_string
|
||||||
|
except IOError as e:
|
||||||
|
raise IOError(f"Error reading image file {image_path}: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
# 그 외 예외 처리
|
||||||
|
raise Exception(f"An unexpected error occurred: {e}")
|
||||||
@@ -15,21 +15,25 @@ email-validator
|
|||||||
requests
|
requests
|
||||||
|
|
||||||
#imagen
|
#imagen
|
||||||
google-cloud-aiplatform
|
# google-cloud-aiplatform
|
||||||
Pillow
|
# Pillow
|
||||||
|
|
||||||
# #bing img
|
# #bing img
|
||||||
aiohttp
|
# aiohttp
|
||||||
regex
|
# regex
|
||||||
requests
|
# requests
|
||||||
httpx
|
# httpx
|
||||||
nest_asyncio
|
# nest_asyncio
|
||||||
|
|
||||||
# #bing art
|
# # #bing art
|
||||||
bingart==1.1.0
|
# bingart==1.1.0
|
||||||
|
|
||||||
#DALL-E 3
|
#DALL-E 3
|
||||||
# openai
|
# openai
|
||||||
|
|
||||||
|
# gemini
|
||||||
|
google-genai
|
||||||
|
pillow
|
||||||
|
|
||||||
# SFTP
|
# SFTP
|
||||||
paramiko
|
paramiko
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import uvicorn
|
|
||||||
from vactor_rest.app.common.config import conf
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
uvicorn.run('vactor_rest.app.main:app', host='0.0.0.0', port=conf().REST_SERVER_PORT, reload=True)
|
|
||||||
6
rest_vector.py
Normal file
6
rest_vector.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import uvicorn
|
||||||
|
from vector_rest.app.common.config import conf
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
uvicorn.run('vector_rest.app.main:app', host='0.0.0.0', port=conf().REST_SERVER_PORT, reload=True)
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from os import path, environ
|
from os import path, environ
|
||||||
|
|
||||||
from vactor_rest.app.common import consts
|
from vector_rest.app.common import consts
|
||||||
from vactor_rest.app.models import UserInfo
|
from vector_rest.app.models import UserInfo
|
||||||
|
|
||||||
base_dir = path.dirname(path.dirname(path.dirname(path.abspath(__file__))))
|
base_dir = path.dirname(path.dirname(path.dirname(path.abspath(__file__))))
|
||||||
|
|
||||||
@@ -12,11 +12,11 @@
|
|||||||
# SUPPORT PROJECT
|
# SUPPORT PROJECT
|
||||||
SUPPORT_PROJECT_BASIC = 'PROJECT_BASIC'
|
SUPPORT_PROJECT_BASIC = 'PROJECT_BASIC'
|
||||||
|
|
||||||
PROJECT_NAME = 'FERMAT-TEST(Vactor REST API)'
|
PROJECT_NAME = 'FERMAT-TEST(Vector REST API)'
|
||||||
SW_TITLE= f'{PROJECT_NAME} - REST API'
|
SW_TITLE= f'{PROJECT_NAME} - REST API'
|
||||||
SW_VERSION = '0.1.0'
|
SW_VERSION = '0.1.0'
|
||||||
SW_DESCRIPTION = f'''
|
SW_DESCRIPTION = f'''
|
||||||
### FERMAT-TEST(Vactor REST API) REST API
|
### FERMAT-TEST(Vector REST API) REST API
|
||||||
|
|
||||||
## API 이용법
|
## API 이용법
|
||||||
- 개별 API 설명과 Request/Response schema 참조
|
- 개별 API 설명과 Request/Response schema 참조
|
||||||
@@ -126,8 +126,8 @@ Base = declarative_base()
|
|||||||
# NOTE(hsj100): ADMINISTRATOR
|
# NOTE(hsj100): ADMINISTRATOR
|
||||||
def create_admin(db_session):
|
def create_admin(db_session):
|
||||||
import bcrypt
|
import bcrypt
|
||||||
from vactor_rest.app.database.schema import Users
|
from vector_rest.app.database.schema import Users
|
||||||
from vactor_rest.app.common.consts import ADMIN_INIT_ACCOUNT_INFO
|
from vector_rest.app.common.consts import ADMIN_INIT_ACCOUNT_INFO
|
||||||
|
|
||||||
session = db_session()
|
session = db_session()
|
||||||
|
|
||||||
@@ -16,10 +16,10 @@ from sqlalchemy import func, desc
|
|||||||
|
|
||||||
from fastapi import APIRouter, Depends, Body
|
from fastapi import APIRouter, Depends, Body
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from vactor_rest.app import models as M
|
from vector_rest.app import models as M
|
||||||
from vactor_rest.app.database.conn import Base, db
|
from vector_rest.app.database.conn import Base, db
|
||||||
from vactor_rest.app.database.schema import Users, UserLog
|
from vector_rest.app.database.schema import Users, UserLog
|
||||||
from vactor_rest.app.utils.extra import query_to_groupby, query_to_groupby_date
|
from vector_rest.app.utils.extra import query_to_groupby, query_to_groupby_date
|
||||||
|
|
||||||
|
|
||||||
def get_month_info_list(start: datetime, end: datetime):
|
def get_month_info_list(start: datetime, end: datetime):
|
||||||
@@ -21,9 +21,9 @@ from sqlalchemy import (
|
|||||||
)
|
)
|
||||||
from sqlalchemy.orm import Session, relationship
|
from sqlalchemy.orm import Session, relationship
|
||||||
|
|
||||||
from vactor_rest.app.database.conn import Base, db
|
from vector_rest.app.database.conn import Base, db
|
||||||
from vactor_rest.app.utils.date_utils import D
|
from vector_rest.app.utils.date_utils import D
|
||||||
from vactor_rest.app.models import (
|
from vector_rest.app.models import (
|
||||||
SexType,
|
SexType,
|
||||||
UserType,
|
UserType,
|
||||||
MemberType,
|
MemberType,
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from vactor_rest.app.common.consts import MAX_API_KEY, MAX_API_WHITELIST
|
from vector_rest.app.common.consts import MAX_API_KEY, MAX_API_WHITELIST
|
||||||
|
|
||||||
|
|
||||||
class StatusCode:
|
class StatusCode:
|
||||||
@@ -20,13 +20,13 @@ from fastapi.responses import JSONResponse
|
|||||||
from starlette.middleware.base import BaseHTTPMiddleware
|
from starlette.middleware.base import BaseHTTPMiddleware
|
||||||
from starlette.middleware.cors import CORSMiddleware
|
from starlette.middleware.cors import CORSMiddleware
|
||||||
|
|
||||||
from vactor_rest.app.common import consts
|
from vector_rest.app.common import consts
|
||||||
|
|
||||||
from vactor_rest.app.database.conn import db
|
from vector_rest.app.database.conn import db
|
||||||
from vactor_rest.app.common.config import conf
|
from vector_rest.app.common.config import conf
|
||||||
from vactor_rest.app.middlewares.token_validator import access_control
|
from vector_rest.app.middlewares.token_validator import access_control
|
||||||
from vactor_rest.app.middlewares.trusted_hosts import TrustedHostMiddleware
|
from vector_rest.app.middlewares.trusted_hosts import TrustedHostMiddleware
|
||||||
from vactor_rest.app.routes import dev, index, auth, users, services
|
from vector_rest.app.routes import dev, index, auth, users, services
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
from custom_logger.vactor_log import vactor_logger as LOG
|
from custom_logger.vactor_log import vactor_logger as LOG
|
||||||
@@ -12,19 +12,19 @@ from jwt.exceptions import ExpiredSignatureError, DecodeError
|
|||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
from starlette.responses import JSONResponse
|
from starlette.responses import JSONResponse
|
||||||
|
|
||||||
from vactor_rest.app.common.consts import EXCEPT_PATH_LIST, EXCEPT_PATH_REGEX
|
from vector_rest.app.common.consts import EXCEPT_PATH_LIST, EXCEPT_PATH_REGEX
|
||||||
from vactor_rest.app.database.conn import db
|
from vector_rest.app.database.conn import db
|
||||||
from vactor_rest.app.database.schema import Users, ApiKeys
|
from vector_rest.app.database.schema import Users, ApiKeys
|
||||||
from vactor_rest.app.errors import exceptions as ex
|
from vector_rest.app.errors import exceptions as ex
|
||||||
|
|
||||||
from vactor_rest.app.common import consts
|
from vector_rest.app.common import consts
|
||||||
from vactor_rest.app.common.config import conf
|
from vector_rest.app.common.config import conf
|
||||||
from vactor_rest.app.errors.exceptions import APIException, SqlFailureEx, APIQueryStringEx
|
from vector_rest.app.errors.exceptions import APIException, SqlFailureEx, APIQueryStringEx
|
||||||
from vactor_rest.app.models import UserToken
|
from vector_rest.app.models import UserToken
|
||||||
|
|
||||||
from vactor_rest.app.utils.date_utils import D
|
from vector_rest.app.utils.date_utils import D
|
||||||
from vactor_rest.app.utils.logger import api_logger
|
from vector_rest.app.utils.logger import api_logger
|
||||||
from vactor_rest.app.utils.query_utils import to_dict
|
from vector_rest.app.utils.query_utils import to_dict
|
||||||
|
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ from pydantic.main import BaseModel
|
|||||||
from pydantic.networks import EmailStr, IPvAnyAddress
|
from pydantic.networks import EmailStr, IPvAnyAddress
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from vactor_rest.app.common.consts import (
|
from vector_rest.app.common.consts import (
|
||||||
SW_TITLE,
|
SW_TITLE,
|
||||||
SW_VERSION,
|
SW_VERSION,
|
||||||
MAIL_REG_TITLE,
|
MAIL_REG_TITLE,
|
||||||
@@ -29,7 +29,7 @@ from vactor_rest.app.common.consts import (
|
|||||||
ADMIN_INIT_ACCOUNT_INFO,
|
ADMIN_INIT_ACCOUNT_INFO,
|
||||||
DEFAULT_USER_ACCOUNT_PW
|
DEFAULT_USER_ACCOUNT_PW
|
||||||
)
|
)
|
||||||
from vactor_rest.app.utils.date_utils import D
|
from vector_rest.app.utils.date_utils import D
|
||||||
|
|
||||||
|
|
||||||
class SWInfo(BaseModel):
|
class SWInfo(BaseModel):
|
||||||
@@ -585,7 +585,7 @@ class VitModelType(str, Enum):
|
|||||||
|
|
||||||
class VactorSearchReq(BaseModel):
|
class VactorSearchReq(BaseModel):
|
||||||
"""
|
"""
|
||||||
### [Request] vactor 검색
|
### [Request] vector 검색
|
||||||
"""
|
"""
|
||||||
query_image_path : str = Field(description='quary image', example='path')
|
query_image_path : str = Field(description='quary image', example='path')
|
||||||
index_type : IndexType = Field(IndexType.l2, description='인덱스 타입', example=IndexType.l2)
|
index_type : IndexType = Field(IndexType.l2, description='인덱스 타입', example=IndexType.l2)
|
||||||
@@ -594,7 +594,7 @@ class VactorSearchReq(BaseModel):
|
|||||||
|
|
||||||
class VactorSearchVitReportReq(BaseModel):
|
class VactorSearchVitReportReq(BaseModel):
|
||||||
"""
|
"""
|
||||||
### [Request] vactor 검색(vit) 후 리포트 이미지 생성
|
### [Request] vector 검색(vit) 후 리포트 이미지 생성
|
||||||
"""
|
"""
|
||||||
query_image_path : str = Field(description='quary image', example='path')
|
query_image_path : str = Field(description='quary image', example='path')
|
||||||
index_type : VitIndexType = Field(IndexType.l2, description='인덱스 타입', example=IndexType.l2)
|
index_type : VitIndexType = Field(IndexType.l2, description='인덱스 타입', example=IndexType.l2)
|
||||||
@@ -604,7 +604,7 @@ class VactorSearchVitReportReq(BaseModel):
|
|||||||
|
|
||||||
class VactorSearchVitReq(BaseModel):
|
class VactorSearchVitReq(BaseModel):
|
||||||
"""
|
"""
|
||||||
### [Request] vactor 검색(vit) 후 이미지 생성
|
### [Request] vector 검색(vit) 후 이미지 생성
|
||||||
"""
|
"""
|
||||||
query_image_path : str = Field(description='quary image', example='path')
|
query_image_path : str = Field(description='quary image', example='path')
|
||||||
index_type : VitIndexType = Field(IndexType.l2, description='인덱스 타입', example=IndexType.l2)
|
index_type : VitIndexType = Field(IndexType.l2, description='인덱스 타입', example=IndexType.l2)
|
||||||
@@ -17,13 +17,13 @@ import bcrypt
|
|||||||
import jwt
|
import jwt
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from vactor_rest.app.common import consts
|
from vector_rest.app.common import consts
|
||||||
from vactor_rest.app import models as M
|
from vector_rest.app import models as M
|
||||||
from vactor_rest.app.database.conn import db
|
from vector_rest.app.database.conn import db
|
||||||
from vactor_rest.app.common.config import conf
|
from vector_rest.app.common.config import conf
|
||||||
from vactor_rest.app.database.schema import Users, UserLog
|
from vector_rest.app.database.schema import Users, UserLog
|
||||||
from vactor_rest.app.utils.extra import query_to_groupby, AESCryptoCBC
|
from vector_rest.app.utils.extra import query_to_groupby, AESCryptoCBC
|
||||||
from vactor_rest.app.utils.date_utils import D
|
from vector_rest.app.utils.date_utils import D
|
||||||
|
|
||||||
router = APIRouter(prefix='/auth')
|
router = APIRouter(prefix='/auth')
|
||||||
|
|
||||||
@@ -15,12 +15,12 @@ from sqlalchemy.orm import Session
|
|||||||
import bcrypt
|
import bcrypt
|
||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
|
|
||||||
from vactor_rest.app.common import consts
|
from vector_rest.app.common import consts
|
||||||
from vactor_rest.app import models as M
|
from vector_rest.app import models as M
|
||||||
from vactor_rest.app.database.conn import db, Base
|
from vector_rest.app.database.conn import db, Base
|
||||||
from vactor_rest.app.database.schema import Users, UserLog
|
from vector_rest.app.database.schema import Users, UserLog
|
||||||
|
|
||||||
from vactor_rest.app.utils.extra import FernetCrypto, AESCryptoCBC, AESCipher
|
from vector_rest.app.utils.extra import FernetCrypto, AESCryptoCBC, AESCipher
|
||||||
from custom_logger.vactor_log import vactor_logger as LOG
|
from custom_logger.vactor_log import vactor_logger as LOG
|
||||||
|
|
||||||
|
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
|
|
||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from vactor_rest.app.utils.date_utils import D
|
from vector_rest.app.utils.date_utils import D
|
||||||
from vactor_rest.app.models import SWInfo
|
from vector_rest.app.models import SWInfo
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
@@ -14,9 +14,9 @@ from fastapi import APIRouter, Depends, Body
|
|||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
from typing import Annotated, List
|
from typing import Annotated, List
|
||||||
|
|
||||||
from vactor_rest.app.common import consts
|
from vector_rest.app.common import consts
|
||||||
from vactor_rest.app import models as M
|
from vector_rest.app import models as M
|
||||||
from vactor_rest.app.utils.date_utils import D
|
from vector_rest.app.utils.date_utils import D
|
||||||
from custom_logger.vactor_log import vactor_logger as LOG
|
from custom_logger.vactor_log import vactor_logger as LOG
|
||||||
|
|
||||||
from custom_apps.faiss_imagenet.main import search_idxs
|
from custom_apps.faiss_imagenet.main import search_idxs
|
||||||
@@ -27,7 +27,7 @@ from custom_apps.FEATURE_VECTOR_SIMILARITY_FAISS.faiss_similarity_search import
|
|||||||
router = APIRouter(prefix="/services")
|
router = APIRouter(prefix="/services")
|
||||||
|
|
||||||
|
|
||||||
@router.post("/faiss/vactor/search/imagenet", summary="imagenet search", response_model=M.ResponseBase)
|
@router.post("/faiss/vector/search/imagenet", summary="imagenet search", response_model=M.ResponseBase)
|
||||||
async def vactor_search(request: Request, request_body_info: M.VactorSearchReq):
|
async def vactor_search(request: Request, request_body_info: M.VactorSearchReq):
|
||||||
"""
|
"""
|
||||||
## 벡터검색
|
## 벡터검색
|
||||||
@@ -38,6 +38,7 @@ async def vactor_search(request: Request, request_body_info: M.VactorSearchReq):
|
|||||||
"""
|
"""
|
||||||
response = M.ResponseBase()
|
response = M.ResponseBase()
|
||||||
try:
|
try:
|
||||||
|
LOG.info(request_body_info.query_image_path)
|
||||||
if os.path.exists(request_body_info.query_image_path):
|
if os.path.exists(request_body_info.query_image_path):
|
||||||
search_idxs(image_path=request_body_info.query_image_path,
|
search_idxs(image_path=request_body_info.query_image_path,
|
||||||
index_type=request_body_info.index_type,
|
index_type=request_body_info.index_type,
|
||||||
@@ -52,7 +53,7 @@ async def vactor_search(request: Request, request_body_info: M.VactorSearchReq):
|
|||||||
return response.set_error(e)
|
return response.set_error(e)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/faiss/vactor/search/vit/report", summary="vit search report", response_model=M.ResponseBase)
|
@router.post("/faiss/vector/search/vit/report", summary="vit search report", response_model=M.ResponseBase)
|
||||||
async def vactor_report_vit(request: Request, request_body_info: M.VactorSearchVitReportReq):
|
async def vactor_report_vit(request: Request, request_body_info: M.VactorSearchVitReportReq):
|
||||||
response = M.ResponseBase()
|
response = M.ResponseBase()
|
||||||
try:
|
try:
|
||||||
@@ -71,8 +72,8 @@ async def vactor_report_vit(request: Request, request_body_info: M.VactorSearchV
|
|||||||
return response.set_error(e)
|
return response.set_error(e)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/faiss/vactor/search/vit", summary="vit search", response_model=M.VactorSearchVitRes)
|
@router.post("/faiss/vector/search/vit", summary="vit search", response_model=M.VactorSearchVitRes)
|
||||||
async def vactor_report_vit(request: Request, request_body_info: M.VactorSearchVitReq):
|
async def vactor_vit(request: Request, request_body_info: M.VactorSearchVitReq):
|
||||||
response = M.VactorSearchVitRes()
|
response = M.VactorSearchVitRes()
|
||||||
try:
|
try:
|
||||||
if not os.path.exists(request_body_info.query_image_path):
|
if not os.path.exists(request_body_info.query_image_path):
|
||||||
@@ -13,13 +13,13 @@ from fastapi import APIRouter
|
|||||||
from starlette.requests import Request
|
from starlette.requests import Request
|
||||||
import bcrypt
|
import bcrypt
|
||||||
|
|
||||||
from vactor_rest.app.common import consts
|
from vector_rest.app.common import consts
|
||||||
from vactor_rest.app import models as M
|
from vector_rest.app import models as M
|
||||||
from vactor_rest.app.common.config import conf
|
from vector_rest.app.common.config import conf
|
||||||
from vactor_rest.app.database.schema import Users
|
from vector_rest.app.database.schema import Users
|
||||||
from vactor_rest.app.database.crud import table_select, table_update, table_delete
|
from vector_rest.app.database.crud import table_select, table_update, table_delete
|
||||||
|
|
||||||
from vactor_rest.app.utils.extra import AESCryptoCBC
|
from vector_rest.app.utils.extra import AESCryptoCBC
|
||||||
|
|
||||||
|
|
||||||
router = APIRouter(prefix='/user')
|
router = APIRouter(prefix='/user')
|
||||||
@@ -26,10 +26,10 @@ from itertools import groupby
|
|||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from vactor_rest.app.common.consts import NUM_RETRY_UUID_GEN, SMTP_HOST, SMTP_PORT
|
from vector_rest.app.common.consts import NUM_RETRY_UUID_GEN, SMTP_HOST, SMTP_PORT
|
||||||
from vactor_rest.app.utils.date_utils import D
|
from vector_rest.app.utils.date_utils import D
|
||||||
from vactor_rest.app import models as M
|
from vector_rest.app import models as M
|
||||||
from vactor_rest.app.common.consts import AES_CBC_PUBLIC_KEY, AES_CBC_IV, FERNET_SECRET_KEY
|
from vector_rest.app.common.consts import AES_CBC_PUBLIC_KEY, AES_CBC_IV, FERNET_SECRET_KEY
|
||||||
|
|
||||||
|
|
||||||
async def send_mail(sender, sender_pw, title, recipient, contents_plain, contents_html, cc_list, smtp_host=SMTP_HOST, smtp_port=SMTP_PORT):
|
async def send_mail(sender, sender_pw, title, recipient, contents_plain, contents_html, cc_list, smtp_host=SMTP_HOST, smtp_port=SMTP_PORT):
|
||||||
Reference in New Issue
Block a user