feat : 代码梳理 移除所有敏感密钥 通过环境变量方式配置
All checks were successful
git commit AiDA python develop 分支构建部署 / scheduled_deploy (push) Has been skipped
All checks were successful
git commit AiDA python develop 分支构建部署 / scheduled_deploy (push) Has been skipped
This commit is contained in:
@@ -2,8 +2,7 @@ import json
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.core.config import DEBUG
|
||||
from app.core.config import settings
|
||||
from app.schemas.attribute_retrieve import *
|
||||
from app.schemas.response_template import ResponseModel
|
||||
from app.service.attribute.config import const, local_debug_const
|
||||
@@ -35,13 +34,13 @@ def attribute_recognition(request_item: list[AttributeRecognitionModel]):
|
||||
"""
|
||||
try:
|
||||
for item in request_item:
|
||||
logger.debug(f"attribute_recognition request item is : @@@@@@:{json.dumps(item.dict())}")
|
||||
if DEBUG:
|
||||
logger.info(f"attribute_recognition request item is : @@@@@@:{json.dumps(item.dict(), indent=4)}")
|
||||
if settings.DEBUG:
|
||||
service = AttributeRecognition(const=local_debug_const, request_data=request_item)
|
||||
else:
|
||||
service = AttributeRecognition(const=const, request_data=request_item)
|
||||
data = service.get_result()
|
||||
logger.debug(f"attribute_recognition response @@@@@@:{json.dumps(data)}")
|
||||
logger.info(f"attribute_recognition response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"attribute_recognition Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
@@ -67,10 +66,10 @@ def category_recognition(request_item: list[CategoryRecognitionModel]):
|
||||
"""
|
||||
try:
|
||||
for item in request_item:
|
||||
logger.info(f"category_recognition request item is : @@@@@@:{json.dumps(item.dict())}")
|
||||
logger.info(f"category_recognition request item is : @@@@@@:{json.dumps(item.dict(), indent=4)}")
|
||||
service = CategoryRecognition(request_data=request_item)
|
||||
data = service.get_result()
|
||||
logger.info(f"category_recognition response @@@@@@:{json.dumps(data)}")
|
||||
logger.info(f"category_recognition response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"category_recognition Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
|
||||
@@ -26,7 +26,7 @@ def seg_product(request_item: BrandDnaModel):
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"brand dna request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"brand dna request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
service = BrandDna(request_item)
|
||||
result_url = service.get_result()
|
||||
except Exception as e:
|
||||
@@ -36,7 +36,7 @@ def seg_product(request_item: BrandDnaModel):
|
||||
|
||||
|
||||
@router.post("/GenerateBrand")
|
||||
def GenerateBrand(request_data: GenerateBrandModel):
|
||||
def generate_brand(request_data: GenerateBrandModel):
|
||||
"""
|
||||
通过prompt 生成 brand name ,brand slogan , brand logo。
|
||||
创建一个具有以下参数的请求体:
|
||||
|
||||
@@ -1,34 +1,25 @@
|
||||
import io
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
from typing import List
|
||||
from collections import defaultdict
|
||||
import numpy as np
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
from fastapi import HTTPException, APIRouter
|
||||
|
||||
import pymysql
|
||||
from app.core.config import DB_CONFIG, TABLE_CATEGORIES, RECOMMEND_PATH_PREFIX
|
||||
from minio import Minio
|
||||
import torch
|
||||
from torchvision import models, transforms
|
||||
from PIL import Image
|
||||
import os
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
import numpy as np
|
||||
import pymysql
|
||||
import torch
|
||||
from PIL import Image
|
||||
from fastapi import HTTPException, APIRouter
|
||||
from fastapi.responses import JSONResponse
|
||||
from minio import Minio
|
||||
from torchvision import models, transforms
|
||||
|
||||
from app.core.mysql_config import DB_CONFIG
|
||||
from app.core.new_config import settings
|
||||
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||||
logger = logging.getLogger()
|
||||
router = APIRouter()
|
||||
|
||||
# MinIO 配置
|
||||
minio_client = Minio(
|
||||
"www.minio.aida.com.hk:12024",
|
||||
access_key="admin",
|
||||
secret_key="Aidlab123123!",
|
||||
secure=True
|
||||
)
|
||||
minio_client = Minio(settings.MINIO_URL, access_key=settings.MINIO_ACCESS, secret_key=settings.MINIO_SECRET, secure=settings.MINIO_SECURE)
|
||||
|
||||
transform = transforms.Compose([
|
||||
transforms.Resize((224, 224)),
|
||||
@@ -67,8 +58,8 @@ def extract_feature_vector_from_resnet(sketch_path: str) -> np.ndarray:
|
||||
|
||||
|
||||
# 预加载
|
||||
BRAND_FEATURES = np.load(f'{RECOMMEND_PATH_PREFIX}brand_feature.npy', allow_pickle=True).item()
|
||||
SYSTEM_FEATURES = np.load(f'{RECOMMEND_PATH_PREFIX}sketch_feature_dict.npy', allow_pickle=True).item()
|
||||
BRAND_FEATURES = np.load(f'{settings.RECOMMEND_PATH_PREFIX}brand_feature.npy', allow_pickle=True).item()
|
||||
SYSTEM_FEATURES = np.load(f'{settings.RECOMMEND_PATH_PREFIX}sketch_feature_dict.npy', allow_pickle=True).item()
|
||||
|
||||
|
||||
def save_sketch_to_iid():
|
||||
@@ -76,11 +67,11 @@ def save_sketch_to_iid():
|
||||
sketch_path: iid
|
||||
for iid, sketch_path in enumerate(SYSTEM_FEATURES.keys(), start=1)
|
||||
}
|
||||
np.save(f"{RECOMMEND_PATH_PREFIX}sketch_to_iid.npy", sketch_to_iid)
|
||||
np.save(f"{settings.RECOMMEND_PATH_PREFIX}sketch_to_iid.npy", sketch_to_iid)
|
||||
|
||||
|
||||
def load_sketch_to_iid():
|
||||
path = f"{RECOMMEND_PATH_PREFIX}sketch_to_iid.npy"
|
||||
path = f"{settings.RECOMMEND_PATH_PREFIX}sketch_to_iid.npy"
|
||||
if os.path.exists(path):
|
||||
return np.load(path, allow_pickle=True).item()
|
||||
save_sketch_to_iid()
|
||||
@@ -90,7 +81,7 @@ def load_sketch_to_iid():
|
||||
sketch_to_iid = load_sketch_to_iid()
|
||||
|
||||
|
||||
def getNewCategory(gender: str, sketch_category: str) -> str:
|
||||
def get_new_category(gender: str, sketch_category: str) -> str:
|
||||
return f"{gender.lower()}_{sketch_category.lower()}"
|
||||
|
||||
|
||||
@@ -103,8 +94,8 @@ def get_category_from_path(path: str) -> str:
|
||||
|
||||
def load_brand_matrix():
|
||||
"""单独加载 brand_matrix 和 brand_index_map"""
|
||||
mat_path = f"{RECOMMEND_PATH_PREFIX}brand_matrix.npy"
|
||||
idx_path = f"{RECOMMEND_PATH_PREFIX}brand_index_map.npy"
|
||||
mat_path = f"{settings.RECOMMEND_PATH_PREFIX}brand_matrix.npy"
|
||||
idx_path = f"{settings.RECOMMEND_PATH_PREFIX}brand_index_map.npy"
|
||||
try:
|
||||
matrix = np.load(mat_path)
|
||||
index_map = np.load(idx_path, allow_pickle=True).item()
|
||||
@@ -113,11 +104,19 @@ def load_brand_matrix():
|
||||
index_map = {}
|
||||
return matrix, index_map
|
||||
|
||||
|
||||
def cosine_similarity(vec1, vec2):
|
||||
"""计算余弦相似度(增加零值处理)"""
|
||||
norm = np.linalg.norm(vec1) * np.linalg.norm(vec2)
|
||||
return np.dot(vec1, vec2) / (norm + 1e-10) if norm != 0 else 0.0
|
||||
|
||||
|
||||
def getNewCategory(gender, sketch_category):
|
||||
print(gender)
|
||||
print(sketch_category)
|
||||
return "None"
|
||||
|
||||
|
||||
def calculate_brand_matrix(sketch_data, brand_id: int) -> np.ndarray:
|
||||
# 1. 收集品牌-分类-特征
|
||||
brand_feature = defaultdict(lambda: defaultdict(list))
|
||||
@@ -164,11 +163,11 @@ def calculate_brand_matrix(sketch_data, brand_id: int) -> np.ndarray:
|
||||
brand_matrix[row_idx, sketch_index[iid]] = cos_sim
|
||||
|
||||
# 7. 持久化
|
||||
np.save(f"{RECOMMEND_PATH_PREFIX}brand_feature_matrix.npy", brand_matrix)
|
||||
np.save(f"{RECOMMEND_PATH_PREFIX}brand_index_map.npy", brand_index_map)
|
||||
np.save(f"{settings.RECOMMEND_PATH_PREFIX}brand_feature_matrix.npy", brand_matrix)
|
||||
np.save(f"{settings.RECOMMEND_PATH_PREFIX}brand_index_map.npy", brand_index_map)
|
||||
|
||||
# 返回该品牌对应行
|
||||
return brand_matrix[row_idx:row_idx+1]
|
||||
return brand_matrix[row_idx:row_idx + 1]
|
||||
|
||||
|
||||
@router.get("/brand_dna_initialize/{brand_id}")
|
||||
@@ -178,14 +177,12 @@ async def brand_dna_initialize(brand_id: int):
|
||||
conn = pymysql.connect(**DB_CONFIG)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT id, img_url, gender, category
|
||||
FROM product_image_attribute
|
||||
WHERE library_id IN (
|
||||
SELECT library_id
|
||||
FROM brand_rel_library
|
||||
WHERE brand_id = %s
|
||||
)
|
||||
""", (brand_id,))
|
||||
SELECT id, img_url, gender, category
|
||||
FROM product_image_attribute
|
||||
WHERE library_id IN (SELECT library_id
|
||||
FROM brand_rel_library
|
||||
WHERE brand_id = %s)
|
||||
""", (brand_id,))
|
||||
sketch_data = cursor.fetchall()
|
||||
|
||||
# 触发计算并持久化,若内部出错会抛异常
|
||||
|
||||
@@ -5,10 +5,11 @@ import time
|
||||
|
||||
from PIL import ImageEnhance
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from minio import Minio
|
||||
from app.core.config import settings
|
||||
from app.schemas.brighten import BrightenModel
|
||||
from app.schemas.response_template import ResponseModel
|
||||
from app.service.utils.oss_client import oss_get_image, oss_upload_image
|
||||
from app.service.utils.new_oss_client import oss_get_image, oss_upload_image
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger()
|
||||
@@ -20,6 +21,9 @@ def increase_brightness(img, factor):
|
||||
return bright_img
|
||||
|
||||
|
||||
minio_client = Minio(settings.MINIO_URL, access_key=settings.MINIO_ACCESS, secret_key=settings.MINIO_SECRET, secure=settings.MINIO_SECURE)
|
||||
|
||||
|
||||
@router.post("/brighten")
|
||||
async def brighten(request_item: BrightenModel):
|
||||
"""
|
||||
@@ -35,14 +39,14 @@ async def brighten(request_item: BrightenModel):
|
||||
"""
|
||||
try:
|
||||
start_time = time.time()
|
||||
logger.info(f"brighten request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
image = oss_get_image(bucket=request_item.image_url.split('/')[0], object_name=request_item.image_url[request_item.image_url.find('/') + 1:], data_type="PIL")
|
||||
logger.info(f"brighten request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
image = oss_get_image(oss_client=minio_client, bucket=request_item.image_url.split('/')[0], object_name=request_item.image_url[request_item.image_url.find('/') + 1:], data_type="PIL")
|
||||
new_image = increase_brightness(image, request_item.brighten_value)
|
||||
image_data = io.BytesIO()
|
||||
new_image.save(image_data, format='PNG')
|
||||
image_data.seek(0)
|
||||
image_bytes = image_data.read()
|
||||
req = oss_upload_image(bucket=request_item.image_url.split('/')[0], object_name=request_item.image_url[request_item.image_url.find('/') + 1:], image_bytes=image_bytes)
|
||||
req = oss_upload_image(oss_client=minio_client, bucket=request_item.image_url.split('/')[0], object_name=request_item.image_url[request_item.image_url.find('/') + 1:], image_bytes=image_bytes)
|
||||
brighten_url = f"{req.bucket_name}/{req.object_name}"
|
||||
logger.info(f"run time is : {time.time() - start_time}")
|
||||
except Exception as e:
|
||||
|
||||
@@ -30,9 +30,9 @@ def chat_robot(request_data: ChatRobotModel):
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"chat_robot request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
logger.info(f"chat_robot request item is : @@@@@@:{json.dumps(request_data.dict(),indent=4)}")
|
||||
data = chat(post_data=request_data)
|
||||
logger.info(f"chat_robot response @@@@@@:{json.dumps(data)}")
|
||||
logger.info(f"chat_robot response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"chat_robot Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
|
||||
@@ -42,7 +42,7 @@ def clothing_seg(request_item: ClothingSegModel):
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"clothing_seg request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"clothing_seg request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
server = ClothingSeg(request_item)
|
||||
result_url = server.get_result()
|
||||
except Exception as e:
|
||||
|
||||
@@ -1,203 +1,201 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from fastapi import APIRouter, HTTPException, UploadFile, File, Form, BackgroundTasks
|
||||
from fastapi import APIRouter, HTTPException, BackgroundTasks
|
||||
|
||||
from app.schemas.design import DesignModel, DesignProgressModel, ModelProgressModel, DBGConfigModel, DesignStreamModel
|
||||
from app.schemas.design import DesignModel, ModelProgressModel, DesignStreamModel
|
||||
from app.schemas.response_template import ResponseModel
|
||||
from app.service.design.model_process_service import model_transpose
|
||||
from app.service.design_batch.service import start_design_batch_generate
|
||||
from app.service.design_fast.design_generate import design_generate, design_generate_v2
|
||||
from app.service.design_fast.utils.redis_utils import Redis
|
||||
from app.service.design_fast.model_process_service import model_transpose
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
@router.post("/design")
|
||||
def design(request_data: DesignModel, background_tasks: BackgroundTasks):
|
||||
def design(request_data: DesignModel):
|
||||
"""
|
||||
objects.items.transparent:
|
||||
"transparent":{
|
||||
"mask_url":"test/transparent_test/transparent_mask.png",
|
||||
"scale":0.1
|
||||
},
|
||||
mask_url 为空"" -> 单件衣服透明
|
||||
mask_url 非空"mask_url" -> 区域透明
|
||||
objects.items.transparent:
|
||||
"transparent":{
|
||||
"mask_url":"test/transparent_test/transparent_mask.png",
|
||||
"scale":0.1
|
||||
},
|
||||
mask_url 为空"" -> 单件衣服透明
|
||||
mask_url 非空"mask_url" -> 区域透明
|
||||
|
||||
创建一个具有以下参数的请求体:
|
||||
示例参数:
|
||||
{
|
||||
"objects": [
|
||||
{
|
||||
"basic": {
|
||||
"body_point_test": {
|
||||
"waistband_right": [
|
||||
200,
|
||||
241
|
||||
],
|
||||
"hand_point_right": [
|
||||
223,
|
||||
297
|
||||
],
|
||||
"waistband_left": [
|
||||
112,
|
||||
241
|
||||
],
|
||||
"hand_point_left": [
|
||||
92,
|
||||
305
|
||||
],
|
||||
"shoulder_left": [
|
||||
99,
|
||||
116
|
||||
],
|
||||
"shoulder_right": [
|
||||
215,
|
||||
116
|
||||
]
|
||||
},
|
||||
"layer_order": true,
|
||||
"scale_bag": 0.7,
|
||||
"scale_earrings": 0.16,
|
||||
"self_template": true,
|
||||
"single_overall": "overall",
|
||||
"switch_category": ""
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"businessId": 270372,
|
||||
"color": "30 28 28",
|
||||
"image_id": 69780,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"path": "aida-sys-image/images/female/trousers/0825000630.jpg",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
"element_path_list": [],
|
||||
"element_scale_list": [],
|
||||
"location": []
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
}
|
||||
创建一个具有以下参数的请求体:
|
||||
示例参数:
|
||||
{
|
||||
"objects": [
|
||||
{
|
||||
"basic": {
|
||||
"body_point_test": {
|
||||
"waistband_right": [
|
||||
203,
|
||||
249
|
||||
],
|
||||
"hand_point_right": [
|
||||
229,
|
||||
343
|
||||
],
|
||||
"waistband_left": [
|
||||
119,
|
||||
248
|
||||
],
|
||||
"hand_point_left": [
|
||||
97,
|
||||
343
|
||||
],
|
||||
"shoulder_left": [
|
||||
108,
|
||||
107
|
||||
],
|
||||
"shoulder_right": [
|
||||
212,
|
||||
107
|
||||
]
|
||||
},
|
||||
"priority": 10,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"type": "Trousers"
|
||||
"layer_order": true,
|
||||
"preview_submit": "submit",
|
||||
"scale_bag": 0.7,
|
||||
"scale_earrings": 0.16,
|
||||
"self_template": true,
|
||||
"single_overall": "overall",
|
||||
"switch_category": ""
|
||||
},
|
||||
{
|
||||
"businessId": 270373,
|
||||
"color": "30 28 28",
|
||||
"image_id": 98243,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"path": "aida-sys-image/images/female/blouse/0902003811.jpg",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
"element_path_list": [],
|
||||
"element_scale_list": [],
|
||||
"location": []
|
||||
"items": [
|
||||
{
|
||||
"businessId": 2377945,
|
||||
"color": "209 196 171",
|
||||
"image_id": 189410,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"path": "aida-collection-element/89/Sketchboard/53d38bd5-f77b-4034-ada2-45f1e2ebe00c.png",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
"element_path_list": [],
|
||||
"element_scale_list": [],
|
||||
"location": []
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
}
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
}
|
||||
"priority": 12,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"seg_mask_url": "aida-clothing/mask/mask_8e96ddb0-e466-11f0-8de2-0242ac130002.png",
|
||||
"type": "Outwear"
|
||||
},
|
||||
"priority": 11,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"type": "Blouse"
|
||||
},
|
||||
{
|
||||
"businessId": 270374,
|
||||
"color": "172 68 68",
|
||||
"image_id": 98244,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"path": "aida-sys-image/images/female/outwear/0825000410.jpg",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
"element_path_list": [],
|
||||
"element_scale_list": [],
|
||||
"location": []
|
||||
{
|
||||
"businessId": 2377946,
|
||||
"color": "122 152 139",
|
||||
"image_id": 81868,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"path": "aida-sys-image/images/female/blouse/0825001443.jpg",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
"element_path_list": [],
|
||||
"element_scale_list": [],
|
||||
"location": []
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
}
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
"priority": 11,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"seg_mask_url": "aida-clothing/mask/mask_8f0fab78-e466-11f0-8de2-0242ac130002.png",
|
||||
"type": "Blouse"
|
||||
},
|
||||
{
|
||||
"businessId": 2377947,
|
||||
"color": "111 78 63",
|
||||
"gradient": "aida-gradient/517c3a4d-aed7-4423-aa99-7b60d3577df1.png",
|
||||
"image_id": 116494,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"path": "aida-sys-image/images/female/skirt/0825000219.jpg",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
"element_path_list": [],
|
||||
"element_scale_list": [],
|
||||
"location": []
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
}
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
}
|
||||
"priority": 10,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"seg_mask_url": "aida-clothing/mask/mask_8f6191fe-e466-11f0-8de2-0242ac130002.png",
|
||||
"type": "Skirt"
|
||||
},
|
||||
"priority": 12,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"transparent":{
|
||||
"mask_url":"test/transparent_test/transparent_mask.png",
|
||||
"scale":0.1
|
||||
},
|
||||
"type": "Outwear"
|
||||
},
|
||||
{
|
||||
"body_path": "aida-sys-image/models/female/5bdfe7ca-64eb-44e4-b03d-8e517520c795.png",
|
||||
"image_id": 96090,
|
||||
"type": "Body"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"process_id": "83"
|
||||
}
|
||||
"""
|
||||
# logger.info(f"design request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
{
|
||||
"body_path": "aida-sys-image/models/female/2e4815b9-1191-419d-94ed-5771239ca4a5.png",
|
||||
"image_id": 67277,
|
||||
"type": "Body"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"process_id": "89"
|
||||
}
|
||||
"""
|
||||
# logger.info(f"design request item is : @@@@@@:{json.dumps(request_data.dict(),indent=4)}")
|
||||
# data = generate(request_data=request_data)
|
||||
# logger.info(f"design response @@@@@@:{json.dumps(data)}")
|
||||
# logger.info(f"design response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
#
|
||||
|
||||
try:
|
||||
logger.info(f"design request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
logger.info(f"design request item is : @@@@@@:{json.dumps(request_data.dict(), indent=4)}")
|
||||
data = design_generate(request_data=request_data)
|
||||
logger.info(f"design response @@@@@@:{json.dumps(data)}")
|
||||
logger.info(f"design response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"design Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
@@ -215,47 +213,48 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
"basic": {
|
||||
"body_point_test": {
|
||||
"waistband_right": [
|
||||
200,
|
||||
241
|
||||
203,
|
||||
249
|
||||
],
|
||||
"hand_point_right": [
|
||||
223,
|
||||
297
|
||||
229,
|
||||
343
|
||||
],
|
||||
"waistband_left": [
|
||||
112,
|
||||
241
|
||||
119,
|
||||
248
|
||||
],
|
||||
"hand_point_left": [
|
||||
92,
|
||||
305
|
||||
97,
|
||||
343
|
||||
],
|
||||
"shoulder_left": [
|
||||
99,
|
||||
116
|
||||
108,
|
||||
107
|
||||
],
|
||||
"relation_type": "System",
|
||||
"shoulder_right": [
|
||||
215,
|
||||
116
|
||||
]
|
||||
212,
|
||||
107
|
||||
],
|
||||
"relation_id": 1020356
|
||||
},
|
||||
"layer_order": true,
|
||||
"layer_order": false,
|
||||
"scale_bag": 0.7,
|
||||
"scale_earrings": 0.16,
|
||||
"self_template": true,
|
||||
"self_template": false,
|
||||
"single_overall": "overall",
|
||||
"switch_category": ""
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"businessId": 270372,
|
||||
"color": "30 28 28",
|
||||
"image_id": 69780,
|
||||
"color": "209 196 171",
|
||||
"image_id": 84093,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
1,
|
||||
1
|
||||
],
|
||||
"path": "aida-sys-image/images/female/trousers/0825000630.jpg",
|
||||
"path": "aida-users/89/sketchboard/female/Outwear/0943d209-7ce0-408c-bc61-83f15da94138.png",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
@@ -264,10 +263,23 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
"location": []
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"location": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"print_angle_list": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
"print_scale_list": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
]
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
@@ -276,22 +288,20 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
"print_scale_list": []
|
||||
}
|
||||
},
|
||||
"priority": 10,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"type": "Trousers"
|
||||
"type": "Outwear"
|
||||
},
|
||||
{
|
||||
"businessId": 270373,
|
||||
"color": "30 28 28",
|
||||
"image_id": 98243,
|
||||
"color": "63 71 73",
|
||||
"image_id": 100496,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
1,
|
||||
1
|
||||
],
|
||||
"path": "aida-sys-image/images/female/blouse/0902003811.jpg",
|
||||
"path": "aida-sys-image/images/female/blouse/0628001684.jpg",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
@@ -300,10 +310,23 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
"location": []
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"location": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"print_angle_list": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
"print_scale_list": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
]
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
@@ -312,7 +335,6 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
"print_scale_list": []
|
||||
}
|
||||
},
|
||||
"priority": 11,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
@@ -320,14 +342,14 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
"type": "Blouse"
|
||||
},
|
||||
{
|
||||
"businessId": 270374,
|
||||
"color": "172 68 68",
|
||||
"image_id": 98244,
|
||||
"color": "111 78 63",
|
||||
"gradient": "aida-gradient/f69b98e8-4248-4f7a-98a2-21bac41bf3e0.png",
|
||||
"image_id": 92193,
|
||||
"offset": [
|
||||
0,
|
||||
0
|
||||
1,
|
||||
1
|
||||
],
|
||||
"path": "aida-sys-image/images/female/outwear/0825000410.jpg",
|
||||
"path": "aida-sys-image/images/female/trousers/0825001160.jpg",
|
||||
"print": {
|
||||
"element": {
|
||||
"element_angle_list": [],
|
||||
@@ -336,10 +358,23 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
"location": []
|
||||
},
|
||||
"overall": {
|
||||
"location": [],
|
||||
"print_angle_list": [],
|
||||
"location": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"print_angle_list": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"print_path_list": [],
|
||||
"print_scale_list": []
|
||||
"print_scale_list": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
]
|
||||
},
|
||||
"single": {
|
||||
"location": [],
|
||||
@@ -348,31 +383,37 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
"print_scale_list": []
|
||||
}
|
||||
},
|
||||
"priority": 12,
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"transparent":{
|
||||
"mask_url":"test/transparent_test/transparent_mask.png",
|
||||
"scale":0.1
|
||||
},
|
||||
"type": "Outwear"
|
||||
"type": "Trousers"
|
||||
},
|
||||
{
|
||||
"body_path": "aida-sys-image/models/female/5bdfe7ca-64eb-44e4-b03d-8e517520c795.png",
|
||||
"image_id": 96090,
|
||||
"body_path": "aida-sys-image/models/female/2e4815b9-1191-419d-94ed-5771239ca4a5.png",
|
||||
"image_id": 67277,
|
||||
"offset": [
|
||||
1,
|
||||
1
|
||||
],
|
||||
"resize_scale": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"type": "Body"
|
||||
}
|
||||
]
|
||||
],
|
||||
"objectSign": "65830966"
|
||||
}
|
||||
],
|
||||
"process_id": "83"
|
||||
"process_id": "4802946666428422",
|
||||
"requestId": "1d1e7641-0d62-4da2-adc0-b4404910723c",
|
||||
"callback_url": "https://api.aida.com.hk/api/third/party/receiveDesignResults"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
# 异步
|
||||
logger.info(f"generate_image request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
logger.info(f"generate_image request item is : @@@@@@:{json.dumps(request_data.dict(), indent=4)}")
|
||||
background_tasks.add_task(design_generate_v2, request_data)
|
||||
except Exception as e:
|
||||
logger.warning(f"design Run Exception @@@@@@:{e}")
|
||||
@@ -380,30 +421,30 @@ async def design_v2(request_data: DesignStreamModel, background_tasks: Backgroun
|
||||
return ResponseModel()
|
||||
|
||||
|
||||
@router.post('/get_progress')
|
||||
def get_progress(request_data: DesignProgressModel):
|
||||
"""
|
||||
获取design 进度
|
||||
创建一个具有以下参数的请求体:
|
||||
- **process_id**: 进度id
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"process_id": "6878547032381675"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"get_progress request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
process_id = request_data.process_id
|
||||
r = Redis()
|
||||
data = r.read(key=process_id)
|
||||
if data is None:
|
||||
raise ValueError(f"No progress ID: {process_id}")
|
||||
logging.info(f"get_progress process_id @@@@@@ : {process_id} , progress : {json.dumps(data)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"get_progress Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel(data=data)
|
||||
# @router.post('/get_progress')
|
||||
# def get_progress(request_data: DesignProgressModel):
|
||||
# """
|
||||
# 获取design 进度
|
||||
# 创建一个具有以下参数的请求体:
|
||||
# - **process_id**: 进度id
|
||||
#
|
||||
# 示例参数:
|
||||
# {
|
||||
# "process_id": "6878547032381675"
|
||||
# }
|
||||
# """
|
||||
# try:
|
||||
# logger.info(f"get_progress request item is : @@@@@@:{json.dumps(request_data.dict(), indent=4)}")
|
||||
# process_id = request_data.process_id
|
||||
# r = Redis()
|
||||
# data = r.read(key=process_id)
|
||||
# if data is None:
|
||||
# raise ValueError(f"No progress ID: {process_id}")
|
||||
# logging.info(f"get_progress process_id @@@@@@ : {process_id} , progress : {json.dumps(data, indent=4)}")
|
||||
# except Exception as e:
|
||||
# logger.warning(f"get_progress Run Exception @@@@@@:{e}")
|
||||
# raise HTTPException(status_code=404, detail=str(e))
|
||||
# return ResponseModel(data=data)
|
||||
|
||||
|
||||
@router.post('/model_process')
|
||||
@@ -419,44 +460,42 @@ def model_process(request_data: ModelProgressModel):
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"model_process request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
logger.info(f"model_process request item is : @@@@@@:{json.dumps(request_data.dict(), indent=4)}")
|
||||
|
||||
data = model_transpose(image_path=request_data.model_path)
|
||||
logger.info(f"model_process response @@@@@@:{json.dumps(data)}")
|
||||
logger.info(f"model_process response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"model_process Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel(data=data)
|
||||
|
||||
|
||||
# ##############################################################
|
||||
|
||||
|
||||
@router.post("/design_batch_generate")
|
||||
async def design_batch(file: UploadFile = File(...),
|
||||
tasks_id: str = Form(...),
|
||||
user_id: str = Form(...),
|
||||
file_name: str = Form(...),
|
||||
total: int = Form(...)
|
||||
):
|
||||
dbg_config = DBGConfigModel(
|
||||
tasks_id=tasks_id,
|
||||
user_id=user_id,
|
||||
file_name=file_name,
|
||||
total=total
|
||||
)
|
||||
contents = await file.read()
|
||||
file_name = file.filename
|
||||
await save_request_file(contents, file_name)
|
||||
return await start_design_batch_generate(dbg_config, contents)
|
||||
|
||||
|
||||
async def save_request_file(contents, file_name):
|
||||
# 创建保存文件的目录(如果不存在)
|
||||
save_dir = os.path.join(os.getcwd(), "service/design_batch", "request_data")
|
||||
if not os.path.exists(save_dir):
|
||||
os.makedirs(save_dir)
|
||||
# 处理文件
|
||||
file_path = os.path.join(save_dir, file_name)
|
||||
with open(file_path, "wb") as f:
|
||||
f.write(contents)
|
||||
"""design 批量处理 停用"""
|
||||
# @router.post("/design_batch_generate")
|
||||
# async def design_batch(file: UploadFile = File(...),
|
||||
# tasks_id: str = Form(...),
|
||||
# user_id: str = Form(...),
|
||||
# file_name: str = Form(...),
|
||||
# total: int = Form(...)
|
||||
# ):
|
||||
# dbg_config = DBGConfigModel(
|
||||
# tasks_id=tasks_id,
|
||||
# user_id=user_id,
|
||||
# file_name=file_name,
|
||||
# total=total
|
||||
# )
|
||||
# contents = await file.read()
|
||||
# file_name = file.filename
|
||||
# await save_request_file(contents, file_name)
|
||||
# return await start_design_batch_generate(dbg_config, contents)
|
||||
#
|
||||
#
|
||||
# async def save_request_file(contents, file_name):
|
||||
# # 创建保存文件的目录(如果不存在)
|
||||
# save_dir = os.path.join(os.getcwd(), "service/design_batch", "request_data")
|
||||
# if not os.path.exists(save_dir):
|
||||
# os.makedirs(save_dir)
|
||||
# # 处理文件
|
||||
# file_path = os.path.join(save_dir, file_name)
|
||||
# with open(file_path, "wb") as f:
|
||||
# f.write(contents)
|
||||
|
||||
@@ -30,10 +30,10 @@ def design_pre_processing(request_data: DesignPreProcessingModel):
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"design_pre_processing request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
logger.info(f"design_pre_processing request item is : @@@@@@:{json.dumps(request_data.dict(), indent=4)}")
|
||||
server = DesignPreprocessing()
|
||||
data = server.pipeline(image_list=request_data.sketches)
|
||||
logger.info(f"design response @@@@@@:{json.dumps(data)}")
|
||||
logger.info(f"design response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"design Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
|
||||
@@ -33,18 +33,30 @@ def generate_image(request_item: GenerateImageModel, background_tasks: Backgroun
|
||||
- **version**: 使用模型版本 fast 或者 high
|
||||
|
||||
示例参数:
|
||||
1. txt 2 img
|
||||
{
|
||||
"tasks_id": "123-89",
|
||||
"prompt": "skeleton sitting by the side of a river looking soulful, concert poster, 4k, artistic",
|
||||
"image_url": "aida-collection-element/87/Printboard/842c09cf-7297-42d9-9e6e-9c17d4a13cb5.jpg",
|
||||
"mode": "img2img",
|
||||
"category": "sketch",
|
||||
"gender": "male",
|
||||
"version": "fast"
|
||||
"tasks_id": "bd2cf809-24bc-49a6-91c9-193c6272a52e-2-89",
|
||||
"prompt": "a single item of sketch of dress, 4k, white background",
|
||||
"image_url": "",
|
||||
"mode": "txt2img",
|
||||
"category": "sketch",
|
||||
"gender": "Female",
|
||||
"version": "fast"
|
||||
}
|
||||
2. img 2 img
|
||||
{
|
||||
"tasks_id": "b861d4fa-5ae3-4a30-9c7a-7ba6bb9aa37b-1-89",
|
||||
"prompt": "a single item of sketch of dress, 4k, white background",
|
||||
"image_url": "aida-collection-element/89/Sketchboard/548da3a2-834f-49a7-b52c-e729c5ab5062.png",
|
||||
"mode": "img2img",
|
||||
"category": "sketch",
|
||||
"gender": "Female",
|
||||
"version": "fast"
|
||||
}
|
||||
|
||||
"""
|
||||
try:
|
||||
logger.info(f"generate_image request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"generate_image request item is : @@@@@@:{json.dumps(request_item.dict(), indent=4)}")
|
||||
service = GenerateImage(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
@@ -65,42 +77,41 @@ def generate_image(tasks_id: str):
|
||||
return ResponseModel(data=data['data'])
|
||||
|
||||
|
||||
'''multi view'''
|
||||
'''multi view 停用'''
|
||||
|
||||
# @router.post("/generate_multi_view")
|
||||
# def generate_multi_view(request_item: GenerateMultiViewModel, background_tasks: BackgroundTasks):
|
||||
# """
|
||||
# 创建一个具有以下参数的请求体:
|
||||
# - **tasks_id**: 任务id 用于取消生成任务和获取生成结果
|
||||
# - **image_url**: 前视角图的输入,minio或S3 url 地址
|
||||
#
|
||||
# 示例参数:
|
||||
# {
|
||||
# "tasks_id": "123-89",
|
||||
# "image_url": "aida-collection-element/87/Printboard/842c09cf-7297-42d9-9e6e-9c17d4a13cb5.jpg"
|
||||
# }
|
||||
# """
|
||||
# try:
|
||||
# logger.info(f"generate_multi_view request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
# service = GenerateMultiView(request_item)
|
||||
# background_tasks.add_task(service.get_result)
|
||||
# except Exception as e:
|
||||
# logger.warning(f"generate_multi_view Run Exception @@@@@@:{e}")
|
||||
# raise HTTPException(status_code=404, detail=str(e))
|
||||
# return ResponseModel()
|
||||
|
||||
|
||||
@router.post("/generate_multi_view")
|
||||
def generate_multi_view(request_item: GenerateMultiViewModel, background_tasks: BackgroundTasks):
|
||||
"""
|
||||
创建一个具有以下参数的请求体:
|
||||
- **tasks_id**: 任务id 用于取消生成任务和获取生成结果
|
||||
- **image_url**: 前视角图的输入,minio或S3 url 地址
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"tasks_id": "123-89",
|
||||
"image_url": "aida-collection-element/87/Printboard/842c09cf-7297-42d9-9e6e-9c17d4a13cb5.jpg"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"generate_multi_view request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
service = GenerateMultiView(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
logger.warning(f"generate_multi_view Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel()
|
||||
|
||||
|
||||
@router.get("/generate_multi_view_cancel/{tasks_id}")
|
||||
def generate_multi_view(tasks_id: str):
|
||||
try:
|
||||
logger.info(f"generate_cancel request item is : @@@@@@:{tasks_id}")
|
||||
data = generate_multi_view_cancel(tasks_id)
|
||||
logger.info(f"generate_cancel response @@@@@@:{data}")
|
||||
except Exception as e:
|
||||
logger.warning(f"generate_cancel Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel(data=data['data'])
|
||||
# @router.get("/generate_multi_view_cancel/{tasks_id}")
|
||||
# def generate_multi_view(tasks_id: str):
|
||||
# try:
|
||||
# logger.info(f"generate_cancel request item is : @@@@@@:{tasks_id}")
|
||||
# data = generate_multi_view_cancel(tasks_id)
|
||||
# logger.info(f"generate_cancel response @@@@@@:{data}")
|
||||
# except Exception as e:
|
||||
# logger.warning(f"generate_cancel Run Exception @@@@@@:{e}")
|
||||
# raise HTTPException(status_code=404, detail=str(e))
|
||||
# return ResponseModel(data=data['data'])
|
||||
|
||||
|
||||
'''single logo'''
|
||||
@@ -122,7 +133,7 @@ def generate_single_logo(request_item: GenerateSingleLogoImageModel, background_
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"generate_single_logo request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"generate_single_logo request item is : @@@@@@:{json.dumps(request_item.dict(), indent=4)}")
|
||||
service = GenerateSingleLogoImage(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
@@ -167,7 +178,7 @@ def generate_product_image(request_item: GenerateProductImageModel, background_t
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"generate_product_image request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"generate_product_image request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
service = GenerateProductImage(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
@@ -188,166 +199,164 @@ def generate_product_image(tasks_id: str):
|
||||
return ResponseModel(data=data['data'])
|
||||
|
||||
|
||||
'''relight image'''
|
||||
'''relight image 停用'''
|
||||
|
||||
# @router.post("/generate_relight_image")
|
||||
# def generate_relight_image(request_item: GenerateRelightImageModel, background_tasks: BackgroundTasks):
|
||||
# """
|
||||
# 创建一个具有以下参数的请求体:
|
||||
# - **tasks_id**: 任务id 用于取消生成任务和获取生成结果
|
||||
# - **prompt**: 想要生成图片的描述词
|
||||
# - **image_url**: 被生成图片的S3或minio url地址
|
||||
# - **direction**: 光源方向 Right Light Left Light Top Light Bottom Light
|
||||
# - **product_type**: 输入single item 还是 overall item
|
||||
#
|
||||
#
|
||||
# 示例参数:
|
||||
# {
|
||||
# "tasks_id": "123-89",
|
||||
# "prompt": "beautiful woman, detailed face, sunshine, outdoor, warm atmosphere",
|
||||
# "image_url": "aida-results/result_0000b606-1902-11ef-9424-0242ac180002.png",
|
||||
# "direction": "Right Light",
|
||||
# "product_type": "overall"
|
||||
# }
|
||||
# """
|
||||
# try:
|
||||
# logger.info(f"generate_relight_image request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
# service = GenerateRelightImage(request_item)
|
||||
# background_tasks.add_task(service.get_result)
|
||||
# except Exception as e:
|
||||
# logger.warning(f"generate_relight_image Run Exception @@@@@@:{e}")
|
||||
# raise HTTPException(status_code=404, detail=str(e))
|
||||
# return ResponseModel()
|
||||
#
|
||||
#
|
||||
# @router.get("/generate_relight_image_cancel_cancel/{tasks_id}")
|
||||
# def generate_relight_image(tasks_id: str):
|
||||
# try:
|
||||
# logger.info(f"generate_relight_image_cancel_cancel request item is : @@@@@@:{tasks_id}")
|
||||
# data = generate_relight_image_cancel(tasks_id)
|
||||
# logger.info(f"generate_relight_image_cancel_cancel response @@@@@@:{data}")
|
||||
# except Exception as e:
|
||||
# logger.warning(f"generate_relight_image_cancel_cancel Run Exception @@@@@@:{e}")
|
||||
# raise HTTPException(status_code=404, detail=str(e))
|
||||
# return ResponseModel(data=data['data'])
|
||||
|
||||
|
||||
@router.post("/generate_relight_image")
|
||||
def generate_relight_image(request_item: GenerateRelightImageModel, background_tasks: BackgroundTasks):
|
||||
"""
|
||||
创建一个具有以下参数的请求体:
|
||||
- **tasks_id**: 任务id 用于取消生成任务和获取生成结果
|
||||
- **prompt**: 想要生成图片的描述词
|
||||
- **image_url**: 被生成图片的S3或minio url地址
|
||||
- **direction**: 光源方向 Right Light Left Light Top Light Bottom Light
|
||||
- **product_type**: 输入single item 还是 overall item
|
||||
"""batch generate img 停用"""
|
||||
|
||||
# @router.post("/batch_generate_product_image")
|
||||
# async def batch_generate_product(request_batch_item: BatchGenerateProductImageModel):
|
||||
# """
|
||||
# 创建一个具有以下参数的请求体:
|
||||
# - **tasks_id**: 任务id 用于获取生成结果
|
||||
# - **prompt**: 想要生成图片的描述词
|
||||
# - **image_url**: 被生成图片的S3或minio url地址
|
||||
# - **image_strength**: 生成强度,越低越接近原图
|
||||
# - **product_type**: 输入single item 还是 overall item
|
||||
# - **batch_size**: 批生成数量
|
||||
#
|
||||
#
|
||||
# 示例参数:
|
||||
# {
|
||||
# "tasks_id": "123-89",
|
||||
# "prompt": "the best quality, masterpiece. detailed, high-res, simple background, studio photography, extremely detailed, updo, detailed face, face, close-up, HDR, UHD, 8K realistic, Highly detailed, simple background, Studio lighting",
|
||||
# "image_url": "aida-results/result_00097282-ebb2-11ee-a822-b48351119060.png",
|
||||
# "image_strength": 0.8,
|
||||
# "product_type": "overall",
|
||||
# "batch_size": 1
|
||||
# }
|
||||
# """
|
||||
# return await start_product_batch_generate(request_batch_item)
|
||||
#
|
||||
#
|
||||
# @router.post("/batch_generate_relight_image")
|
||||
# async def batch_generate_relight(request_batch_item: BatchGenerateRelightImageModel):
|
||||
# """
|
||||
# 创建一个具有以下参数的请求体:
|
||||
# - **tasks_id**: 任务id 用于获取生成结果
|
||||
# - **prompt**: 想要生成图片的描述词
|
||||
# - **image_url**: 被生成图片的S3或minio url地址
|
||||
# - **direction**: 光源方向 Right Light Left Light Top Light Bottom Light
|
||||
# - **product_type**: 输入single item 还是 overall item
|
||||
# - **batch_size**: 批生成数量
|
||||
#
|
||||
#
|
||||
# 示例参数:
|
||||
# {
|
||||
# "tasks_id": "123-89",
|
||||
# "prompt": "beautiful woman, detailed face, sunshine, outdoor, warm atmosphere",
|
||||
# "image_url": "aida-results/result_0000b606-1902-11ef-9424-0242ac180002.png",
|
||||
# "direction": "Right Light",
|
||||
# "product_type": "overall",
|
||||
# "batch_size": 1
|
||||
# }
|
||||
# """
|
||||
# return await start_relight_batch_generate(request_batch_item)
|
||||
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"tasks_id": "123-89",
|
||||
"prompt": "beautiful woman, detailed face, sunshine, outdoor, warm atmosphere",
|
||||
"image_url": "aida-results/result_0000b606-1902-11ef-9424-0242ac180002.png",
|
||||
"direction": "Right Light",
|
||||
"product_type": "overall"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"generate_relight_image request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
service = GenerateRelightImage(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
logger.warning(f"generate_relight_image Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel()
|
||||
|
||||
|
||||
@router.get("/generate_relight_image_cancel_cancel/{tasks_id}")
|
||||
def generate_relight_image(tasks_id: str):
|
||||
try:
|
||||
logger.info(f"generate_relight_image_cancel_cancel request item is : @@@@@@:{tasks_id}")
|
||||
data = generate_relight_image_cancel(tasks_id)
|
||||
logger.info(f"generate_relight_image_cancel_cancel response @@@@@@:{data}")
|
||||
except Exception as e:
|
||||
logger.warning(f"generate_relight_image_cancel_cancel Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel(data=data['data'])
|
||||
|
||||
|
||||
"""batch generate img"""
|
||||
|
||||
|
||||
@router.post("/batch_generate_product_image")
|
||||
async def batch_generate_product(request_batch_item: BatchGenerateProductImageModel):
|
||||
"""
|
||||
创建一个具有以下参数的请求体:
|
||||
- **tasks_id**: 任务id 用于获取生成结果
|
||||
- **prompt**: 想要生成图片的描述词
|
||||
- **image_url**: 被生成图片的S3或minio url地址
|
||||
- **image_strength**: 生成强度,越低越接近原图
|
||||
- **product_type**: 输入single item 还是 overall item
|
||||
- **batch_size**: 批生成数量
|
||||
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"tasks_id": "123-89",
|
||||
"prompt": "the best quality, masterpiece. detailed, high-res, simple background, studio photography, extremely detailed, updo, detailed face, face, close-up, HDR, UHD, 8K realistic, Highly detailed, simple background, Studio lighting",
|
||||
"image_url": "aida-results/result_00097282-ebb2-11ee-a822-b48351119060.png",
|
||||
"image_strength": 0.8,
|
||||
"product_type": "overall",
|
||||
"batch_size": 1
|
||||
}
|
||||
"""
|
||||
return await start_product_batch_generate(request_batch_item)
|
||||
|
||||
|
||||
@router.post("/batch_generate_relight_image")
|
||||
async def batch_generate_relight(request_batch_item: BatchGenerateRelightImageModel):
|
||||
"""
|
||||
创建一个具有以下参数的请求体:
|
||||
- **tasks_id**: 任务id 用于获取生成结果
|
||||
- **prompt**: 想要生成图片的描述词
|
||||
- **image_url**: 被生成图片的S3或minio url地址
|
||||
- **direction**: 光源方向 Right Light Left Light Top Light Bottom Light
|
||||
- **product_type**: 输入single item 还是 overall item
|
||||
- **batch_size**: 批生成数量
|
||||
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"tasks_id": "123-89",
|
||||
"prompt": "beautiful woman, detailed face, sunshine, outdoor, warm atmosphere",
|
||||
"image_url": "aida-results/result_0000b606-1902-11ef-9424-0242ac180002.png",
|
||||
"direction": "Right Light",
|
||||
"product_type": "overall",
|
||||
"batch_size": 1
|
||||
}
|
||||
"""
|
||||
return await start_relight_batch_generate(request_batch_item)
|
||||
|
||||
|
||||
@router.post("/batch_generate_pose_transform_image")
|
||||
async def batch_generate_pose_transform(request_batch_item: BatchPoseTransformModel):
|
||||
"""
|
||||
创建一个具有以下参数的请求体:
|
||||
- **tasks_id**: 任务id 用于取消生成任务和获取生成结果
|
||||
- **image_url**: 被生成图片的S3或minio url地址
|
||||
- **pose_id**: 1
|
||||
- **batch_size**: 批生成数量
|
||||
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"tasks_id": "123-89",
|
||||
"image_url": "aida-results/result_0000b606-1902-11ef-9424-0242ac180002.png",
|
||||
"pose_id": "1",
|
||||
"batch_size": 1
|
||||
}
|
||||
"""
|
||||
return await start_pose_transform_batch_generate(request_batch_item)
|
||||
|
||||
|
||||
"""agent tool"""
|
||||
|
||||
|
||||
@router.post("/agent_tool_generate_image")
|
||||
def agent_tool_generate_image(request_item: AgentTollGenerateImageModel, background_tasks: BackgroundTasks):
|
||||
"""
|
||||
创建一个具有以下参数的请求体:
|
||||
- **prompt**: 想要生成图片的描述词
|
||||
- **category**: 生成图片的类别,sketch print 等等
|
||||
- **gender**: 生成sketch专用,服装类别
|
||||
- **version**: 使用模型版本 fast 或者 high
|
||||
- **size**: 生成数量
|
||||
- **version**: 使用模型版本 fast 或者 high
|
||||
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"prompt": "a single item of sketch of Wabi-sabi, skirt, tiered, 4k, white background",
|
||||
"category": "sketch",
|
||||
"gender": "male",
|
||||
"size":2,
|
||||
"version":"high"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"agent_tool_generate_image request item is : @@@@@@:{request_item.dict()}")
|
||||
request_data = request_item.dict()
|
||||
service = AgentToolGenerateImage(request_data['version'])
|
||||
image_url_list, clothing_category_list = service.get_result(
|
||||
prompt=request_data['prompt'],
|
||||
size=request_data['size'],
|
||||
version=request_data['version'],
|
||||
category=request_data['category'],
|
||||
gender=request_data['gender']
|
||||
)
|
||||
data = {
|
||||
"image_url_list": image_url_list,
|
||||
"clothing_category_list": clothing_category_list
|
||||
}
|
||||
logger.info(f"agent_tool_generate_image response item is : @@@@@@:{data}")
|
||||
except Exception as e:
|
||||
logger.warning(f"agent_tool_generate_image Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel(data=data)
|
||||
# @router.post("/batch_generate_pose_transform_image")
|
||||
# async def batch_generate_pose_transform(request_batch_item: BatchPoseTransformModel):
|
||||
# """
|
||||
# 创建一个具有以下参数的请求体:
|
||||
# - **tasks_id**: 任务id 用于取消生成任务和获取生成结果
|
||||
# - **image_url**: 被生成图片的S3或minio url地址
|
||||
# - **pose_id**: 1
|
||||
# - **batch_size**: 批生成数量
|
||||
#
|
||||
#
|
||||
# 示例参数:
|
||||
# {
|
||||
# "tasks_id": "123-89",
|
||||
# "image_url": "aida-results/result_0000b606-1902-11ef-9424-0242ac180002.png",
|
||||
# "pose_id": "1",
|
||||
# "batch_size": 1
|
||||
# }
|
||||
# """
|
||||
# return await start_pose_transform_batch_generate(request_batch_item)
|
||||
#
|
||||
#
|
||||
# """agent tool"""
|
||||
#
|
||||
#
|
||||
# @router.post("/agent_tool_generate_image")
|
||||
# def agent_tool_generate_image(request_item: AgentTollGenerateImageModel):
|
||||
# """
|
||||
# 创建一个具有以下参数的请求体:
|
||||
# - **prompt**: 想要生成图片的描述词
|
||||
# - **category**: 生成图片的类别,sketch print 等等
|
||||
# - **gender**: 生成sketch专用,服装类别
|
||||
# - **version**: 使用模型版本 fast 或者 high
|
||||
# - **size**: 生成数量
|
||||
# - **version**: 使用模型版本 fast 或者 high
|
||||
#
|
||||
#
|
||||
# 示例参数:
|
||||
# {
|
||||
# "prompt": "a single item of sketch of Wabi-sabi, skirt, tiered, 4k, white background",
|
||||
# "category": "sketch",
|
||||
# "gender": "male",
|
||||
# "size":2,
|
||||
# "version":"high"
|
||||
# }
|
||||
# """
|
||||
# try:
|
||||
# logger.info(f"agent_tool_generate_image request item is : @@@@@@:{request_item.dict()}")
|
||||
# request_data = request_item.dict()
|
||||
# service = AgentToolGenerateImage(request_data['version'])
|
||||
# image_url_list, clothing_category_list = service.get_result(
|
||||
# prompt=request_data['prompt'],
|
||||
# size=request_data['size'],
|
||||
# version=request_data['version'],
|
||||
# category=request_data['category'],
|
||||
# gender=request_data['gender']
|
||||
# )
|
||||
# data = {
|
||||
# "image_url_list": image_url_list,
|
||||
# "clothing_category_list": clothing_category_list
|
||||
# }
|
||||
# logger.info(f"agent_tool_generate_image response item is : @@@@@@:{data}")
|
||||
# except Exception as e:
|
||||
# logger.warning(f"agent_tool_generate_image Run Exception @@@@@@:{e}")
|
||||
# raise HTTPException(status_code=404, detail=str(e))
|
||||
# return ResponseModel(data=data)
|
||||
|
||||
@@ -14,22 +14,22 @@ logger = logging.getLogger()
|
||||
@router.post("/image2sketch")
|
||||
def image2sketch(request_item: Image2SketchModel):
|
||||
"""
|
||||
创建一个具有以下参数的请求体:
|
||||
- **image_url**: 提取图片url
|
||||
- **default_style**: 原始、 1、2、3、4、5
|
||||
- **sketch_bucket**: sketch保存的bucket
|
||||
- **sketch_name**: sketch保存的object name
|
||||
创建一个具有以下参数的请求体:
|
||||
- **image_url**: 提取图片url
|
||||
- **default_style**: 原始、 1、2、3、4、5
|
||||
- **sketch_bucket**: sketch保存的bucket
|
||||
- **sketch_name**: sketch保存的object name
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"image_url": "test/image2sketch/real_Dress_3200fecdc83d0c556c2bd96aedbd7fbf.jpg_Img.jpg",
|
||||
"default_style": 0,
|
||||
"sketch_bucket": "test",
|
||||
"sketch_name": "image2sketch/area_fill_img.png"
|
||||
}
|
||||
"""
|
||||
示例参数:
|
||||
{
|
||||
"image_url": "test/image2sketch/real_Dress_3200fecdc83d0c556c2bd96aedbd7fbf.jpg_Img.jpg",
|
||||
"default_style": 0,
|
||||
"sketch_bucket": "test",
|
||||
"sketch_name": "image2sketch/area_fill_img.png"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"image2sketch request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"image2sketch request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
service = LineArtService(request_item)
|
||||
result_url = service.get_result()
|
||||
except Exception as e:
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
import logging
|
||||
import sys
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import threading
|
||||
|
||||
from app.schemas.response_template import ResponseModel
|
||||
from app.service.recommendation_system.import_sys_sketch_to_milvus import main as import_main
|
||||
|
||||
logger = logging.getLogger()
|
||||
router = APIRouter()
|
||||
|
||||
# 使用线程池执行器来运行长时间任务
|
||||
executor = ThreadPoolExecutor(max_workers=1)
|
||||
# 用于跟踪任务状态
|
||||
task_status = {"running": False}
|
||||
|
||||
|
||||
def run_import_task(batch_size: int, retry_times: int, limit: Optional[int], offset: int, skip_create_collection: bool):
|
||||
"""在后台线程中运行导入任务"""
|
||||
original_argv = None
|
||||
try:
|
||||
task_status["running"] = True
|
||||
# 保存原始 sys.argv
|
||||
original_argv = sys.argv.copy()
|
||||
|
||||
# 模拟命令行参数
|
||||
sys.argv = [
|
||||
"import_sys_sketch_to_milvus.py",
|
||||
"--batch-size", str(batch_size),
|
||||
"--retry-times", str(retry_times),
|
||||
]
|
||||
if limit is not None:
|
||||
sys.argv.extend(["--limit", str(limit)])
|
||||
if offset > 0:
|
||||
sys.argv.extend(["--offset", str(offset)])
|
||||
if skip_create_collection:
|
||||
sys.argv.append("--skip-create-collection")
|
||||
|
||||
import_main()
|
||||
task_status["running"] = False
|
||||
logger.info("导入任务完成")
|
||||
except Exception as e:
|
||||
task_status["running"] = False
|
||||
logger.error(f"导入任务失败: {e}", exc_info=True)
|
||||
raise
|
||||
finally:
|
||||
# 恢复原始 sys.argv
|
||||
if original_argv is not None:
|
||||
sys.argv = original_argv
|
||||
|
||||
|
||||
@router.post("/import-sys-sketch", response_model=ResponseModel)
|
||||
async def import_sys_sketch(
|
||||
batch_size: int = Query(1000, description="批量处理大小(默认:1000)"),
|
||||
retry_times: int = Query(3, description="失败重试次数(默认:3)"),
|
||||
limit: Optional[int] = Query(None, description="限制处理数量(用于测试,默认:不限制)"),
|
||||
offset: int = Query(0, description="起始偏移量(默认:0)"),
|
||||
skip_create_collection: bool = Query(False, description="跳过创建集合(如果集合已存在)"),
|
||||
):
|
||||
"""
|
||||
从 t_sys_file 导入系统图向量到 Milvus
|
||||
|
||||
该接口会异步执行导入任务,任务在后台运行。
|
||||
"""
|
||||
try:
|
||||
# 检查是否有任务正在运行
|
||||
if task_status["running"]:
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail="已有导入任务正在运行,请等待完成后再试"
|
||||
)
|
||||
|
||||
# 在后台线程中执行任务
|
||||
executor.submit(
|
||||
run_import_task,
|
||||
batch_size,
|
||||
retry_times,
|
||||
limit,
|
||||
offset,
|
||||
skip_create_collection
|
||||
)
|
||||
|
||||
return ResponseModel(
|
||||
code=200,
|
||||
msg="导入任务已启动,正在后台执行",
|
||||
data={
|
||||
"status": "started",
|
||||
"batch_size": batch_size,
|
||||
"retry_times": retry_times,
|
||||
"limit": limit,
|
||||
"offset": offset,
|
||||
"skip_create_collection": skip_create_collection
|
||||
}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"启动导入任务失败: {e}", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=f"启动导入任务失败: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/import-sys-sketch/status", response_model=ResponseModel)
|
||||
async def get_import_status():
|
||||
"""
|
||||
获取导入任务状态
|
||||
"""
|
||||
return ResponseModel(
|
||||
code=200,
|
||||
msg="OK",
|
||||
data={
|
||||
"running": task_status["running"]
|
||||
}
|
||||
)
|
||||
|
||||
@@ -35,10 +35,10 @@ def mannequins_edit(request_data: MannequinModel):
|
||||
}**
|
||||
"""
|
||||
try:
|
||||
logger.info(f"mannequins_edit request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
logger.info(f"mannequins_edit request item is : @@@@@@:{json.dumps(request_data.dict(),indent=4)}")
|
||||
service = MannequinEditService(request_data)
|
||||
data = service()
|
||||
logger.info(f"mannequins_edit response @@@@@@:{json.dumps(data)}")
|
||||
logger.info(f"mannequins_edit response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"mannequins_edit Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
|
||||
@@ -4,55 +4,55 @@ import logging
|
||||
import requests
|
||||
from fastapi import APIRouter, BackgroundTasks, HTTPException
|
||||
|
||||
from app.core.config import COMFYUI_SERVER_ADDRESS
|
||||
from app.core.config import settings
|
||||
from app.schemas.comfyui_i2v import ComfyuiI2VModel, ComfyuiFLF2VModel
|
||||
from app.schemas.pose_transform import PoseTransformModel
|
||||
from app.schemas.response_template import ResponseModel
|
||||
from app.service.comfyui_I2V.flf2v_server import ComfyUIServerFLF2V
|
||||
from app.service.comfyui_I2V.i2v_server import ComfyUIServerI2V
|
||||
from app.service.comfyui_I2V.pose2v_server import ComfyUIServerPose2V
|
||||
from app.service.generate_image.service_pose_transform import PoseTransformService, infer_cancel as pose_transform_infer_cancel
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger()
|
||||
|
||||
"""停用"""
|
||||
|
||||
@router.post("/pose_transform")
|
||||
def pose_transform(request_item: PoseTransformModel, background_tasks: BackgroundTasks):
|
||||
"""
|
||||
创建一个具有以下参数的请求体:
|
||||
- **tasks_id**: 任务id 用于取消生成任务和获取生成结果
|
||||
- **image_url**: 被生成图片的S3或minio url地址
|
||||
- **pose_id**: 1
|
||||
# @router.post("/pose_transform")
|
||||
# def pose_transform(request_item: PoseTransformModel, background_tasks: BackgroundTasks):
|
||||
# """
|
||||
# 创建一个具有以下参数的请求体:
|
||||
# - **tasks_id**: 任务id 用于取消生成任务和获取生成结果
|
||||
# - **image_url**: 被生成图片的S3或minio url地址
|
||||
# - **pose_id**: 1
|
||||
#
|
||||
#
|
||||
# 示例参数:
|
||||
# {
|
||||
# "tasks_id": "123-89",
|
||||
# "image_url": "aida-results/result_0000b606-1902-11ef-9424-0242ac180002.png",
|
||||
# "pose_id": "1"
|
||||
# }
|
||||
# """
|
||||
# try:
|
||||
# logger.info(f"pose_transform request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
# service = PoseTransformService(request_item)
|
||||
# background_tasks.add_task(service.get_result)
|
||||
# except Exception as e:
|
||||
# logger.warning(f"pose_transform Run Exception @@@@@@:{e}")
|
||||
# raise HTTPException(status_code=404, detail=str(e))
|
||||
# return ResponseModel()
|
||||
|
||||
|
||||
示例参数:
|
||||
{
|
||||
"tasks_id": "123-89",
|
||||
"image_url": "aida-results/result_0000b606-1902-11ef-9424-0242ac180002.png",
|
||||
"pose_id": "1"
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"pose_transform request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
service = PoseTransformService(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
logger.warning(f"pose_transform Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel()
|
||||
|
||||
|
||||
@router.get("/pose_transform_cancel/{tasks_id}")
|
||||
def pose_transform_cancel(tasks_id: str):
|
||||
try:
|
||||
logger.info(f"pose_transform_cancel request item is : @@@@@@:{tasks_id}")
|
||||
data = pose_transform_infer_cancel(tasks_id)
|
||||
logger.info(f"pose_transform_cancel response @@@@@@:{data}")
|
||||
except Exception as e:
|
||||
logger.warning(f"pose_transform_cancel Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel(data=data['data'])
|
||||
# @router.get("/pose_transform_cancel/{tasks_id}")
|
||||
# def pose_transform_cancel(tasks_id: str):
|
||||
# try:
|
||||
# logger.info(f"pose_transform_cancel request item is : @@@@@@:{tasks_id}")
|
||||
# data = pose_transform_infer_cancel(tasks_id)
|
||||
# logger.info(f"pose_transform_cancel response @@@@@@:{data}")
|
||||
# except Exception as e:
|
||||
# logger.warning(f"pose_transform_cancel Run Exception @@@@@@:{e}")
|
||||
# raise HTTPException(status_code=404, detail=str(e))
|
||||
# return ResponseModel(data=data['data'])
|
||||
|
||||
|
||||
"""
|
||||
@@ -77,7 +77,7 @@ def comfyui_image_pose_2_video(request_item: PoseTransformModel, background_task
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"image_pose_2_video request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"image_pose_2_video request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
service = ComfyUIServerPose2V(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
@@ -107,7 +107,7 @@ def comfyui_image_2_video(request_item: ComfyuiI2VModel, background_tasks: Backg
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"image_2_video request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"image_2_video request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
service = ComfyUIServerI2V(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
@@ -139,7 +139,7 @@ def comfyui_flf_2_video(request_item: ComfyuiFLF2VModel, background_tasks: Backg
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"flf_2_video request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"flf_2_video request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
service = ComfyUIServerFLF2V(request_item)
|
||||
background_tasks.add_task(service.get_result)
|
||||
except Exception as e:
|
||||
@@ -153,7 +153,7 @@ def comfyui_i_2_video_cancel(tasks_id: str):
|
||||
try:
|
||||
logger.info(f"comfyui_i_2_video_cancel request item is : @@@@@@:{tasks_id}")
|
||||
response = requests.post(
|
||||
f"http://{COMFYUI_SERVER_ADDRESS}/interrupt",
|
||||
f"http://{settings.COMFYUI_SERVER_ADDRESS}/interrupt",
|
||||
json={"prompt_id": tasks_id}
|
||||
)
|
||||
data = {}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import logging
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from app.schemas.response_template import ResponseModel
|
||||
from app.service.recommendation_system.precompute import run_precompute
|
||||
|
||||
logger = logging.getLogger()
|
||||
router = APIRouter()
|
||||
|
||||
# 使用线程池执行器来运行长时间任务
|
||||
executor = ThreadPoolExecutor(max_workers=1)
|
||||
# 用于跟踪任务状态
|
||||
task_status = {"running": False}
|
||||
|
||||
|
||||
def run_precompute_task():
|
||||
"""在后台线程中运行预计算任务"""
|
||||
try:
|
||||
task_status["running"] = True
|
||||
logger.info("开始执行预计算任务...")
|
||||
run_precompute()
|
||||
task_status["running"] = False
|
||||
logger.info("预计算任务完成")
|
||||
except Exception as e:
|
||||
task_status["running"] = False
|
||||
logger.error(f"预计算任务失败: {e}", exc_info=True)
|
||||
raise
|
||||
|
||||
|
||||
@router.post("/precompute", response_model=ResponseModel)
|
||||
async def precompute():
|
||||
"""
|
||||
运行预计算任务
|
||||
|
||||
该接口会异步执行预计算任务,包括:
|
||||
1. 优化数据库表结构
|
||||
2. 历史数据迁移
|
||||
3. 初始用户偏好向量生成
|
||||
|
||||
任务在后台运行。
|
||||
"""
|
||||
try:
|
||||
# 检查是否有任务正在运行
|
||||
if task_status["running"]:
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail="已有预计算任务正在运行,请等待完成后再试"
|
||||
)
|
||||
|
||||
# 在后台线程中执行任务
|
||||
executor.submit(run_precompute_task)
|
||||
|
||||
return ResponseModel(
|
||||
code=200,
|
||||
msg="预计算任务已启动,正在后台执行",
|
||||
data={
|
||||
"status": "started",
|
||||
"tasks": [
|
||||
"优化数据库表结构",
|
||||
"历史数据迁移",
|
||||
"初始用户偏好向量生成"
|
||||
]
|
||||
}
|
||||
)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"启动预计算任务失败: {e}", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=f"启动预计算任务失败: {str(e)}")
|
||||
|
||||
|
||||
@router.get("/precompute/status", response_model=ResponseModel)
|
||||
async def get_precompute_status():
|
||||
"""
|
||||
获取预计算任务状态
|
||||
"""
|
||||
return ResponseModel(
|
||||
code=200,
|
||||
msg="OK",
|
||||
data={
|
||||
"running": task_status["running"]
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.schemas.prompt_generation import PromptGenerationImageModel, ImageRequest
|
||||
from app.schemas.response_template import ResponseModel
|
||||
from app.service.prompt_generation.chatgpt_for_translation import get_translation_from_llama3, \
|
||||
get_prompt_from_image
|
||||
from app.service.prompt_generation.chatgpt_for_translation import get_translation_from_llama3, get_prompt_from_image
|
||||
|
||||
router = APIRouter()
|
||||
logger = logging.getLogger()
|
||||
@@ -34,19 +31,19 @@ def prompt_generation(request_data: PromptGenerationImageModel):
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return ResponseModel(data=data)
|
||||
|
||||
|
||||
@router.post("/img2prompt")
|
||||
def get_prompt_from_img(img: ImageRequest):
|
||||
"""
|
||||
自动识别图片并输出为prompt
|
||||
|
||||
:param img: 图片的minio地址
|
||||
:return: 图片的文字描述
|
||||
"""
|
||||
text = ("Please describe the clothing in the image and provide a line art description of the outfit. "
|
||||
"The description should allow for the reconstruction of the corresponding line art based on the details "
|
||||
"given.")
|
||||
logger.info(f"get_prompt_from_img request item is : @@@@@@:{img}")
|
||||
description = get_prompt_from_image(img, text)
|
||||
logger.info(f"生成的图片描述 response @@@@@@:{description}")
|
||||
return description
|
||||
# 停用
|
||||
# @router.post("/img2prompt")
|
||||
# def get_prompt_from_img(img: ImageRequest):
|
||||
# """
|
||||
# 自动识别图片并输出为prompt
|
||||
#
|
||||
# :param img: 图片的minio地址
|
||||
# :return: 图片的文字描述
|
||||
# """
|
||||
# text = ("Please describe the clothing in the image and provide a line art description of the outfit. "
|
||||
# "The description should allow for the reconstruction of the corresponding line art based on the details "
|
||||
# "given.")
|
||||
# logger.info(f"get_prompt_from_img request item is : @@@@@@:{img}")
|
||||
# description = get_prompt_from_image(img, text)
|
||||
# logger.info(f"生成的图片描述 response @@@@@@:{description}")
|
||||
# return description
|
||||
|
||||
@@ -26,9 +26,9 @@ def query_image(request_data: QueryImageModel):
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"query_image request item is : @@@@@@:{json.dumps(request_data.dict())}")
|
||||
logger.info(f"query_image request item is : @@@@@@:{json.dumps(request_data.dict(), indent=4)}")
|
||||
data = query(request_data.gender, request_data.content)
|
||||
logger.info(f"query_image response @@@@@@:{json.dumps(data)}")
|
||||
logger.info(f"query_image response @@@@@@:{json.dumps(data, indent=4)}")
|
||||
except Exception as e:
|
||||
logger.warning(f"query_image Run Exception @@@@@@:{e}")
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
|
||||
@@ -1,175 +1,206 @@
|
||||
import io
|
||||
import logging
|
||||
import math
|
||||
import sys
|
||||
from typing import List, Optional
|
||||
from fastapi import HTTPException, APIRouter, Query
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
import time
|
||||
from typing import List
|
||||
|
||||
from app.service.recommendation_system.recommendation_api import get_recommendations as get_new_recommendations
|
||||
from app.service.recommendation_system.incremental_listener import start_background_listener
|
||||
from app.service.recommendation_system.milvus_client import create_collection
|
||||
import numpy as np
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
from fastapi import HTTPException, APIRouter
|
||||
|
||||
from app.service.recommend.service import load_resources, matrix_data
|
||||
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||||
logger = logging.getLogger()
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
# ========== 旧版推荐接口(基于 npy 矩阵,已废弃)==========
|
||||
# @router.get("/recommend/{user_id}/{category}/{num_recommendations}/{brand_id}/{brand_scale}", response_model=List[str])
|
||||
# async def get_recommendations(user_id: int, category: str, brand_id: int, brand_scale: float, num_recommendations: int = 10):
|
||||
# """
|
||||
# :param user_id: 4
|
||||
# :param category: female_skirt
|
||||
# :param num_recommendations: 1
|
||||
# :return:
|
||||
# [
|
||||
# "aida-sys-image/images/female/skirt/903000017.jpg"
|
||||
# ]
|
||||
# """
|
||||
# try:
|
||||
# start_time = time.time()
|
||||
# cache_key = (user_id, category)
|
||||
# # === 新增:用户存在性检查 ===
|
||||
# user_exists_inter = user_id in matrix_data["user_index_interaction"]
|
||||
# user_exists_feat = user_id in matrix_data["user_index_feature"]
|
||||
#
|
||||
# # 任一矩阵不存在用户则返回随机推荐
|
||||
# if not (user_exists_inter and user_exists_feat):
|
||||
# logger.info(f"用户 {user_id} 数据不完整,触发随机推荐")
|
||||
# return get_random_recommendations(category, num_recommendations)
|
||||
#
|
||||
# # 检查缓存
|
||||
# if cache_key in matrix_data["cached_scores"]:
|
||||
# processed_inter, processed_feat = matrix_data["cached_scores"][cache_key]
|
||||
# valid_sketch_idxs_inter = matrix_data["cached_valid_idxs"][cache_key]
|
||||
# else:
|
||||
# # 实时计算逻辑(同原代码)
|
||||
# user_idx_inter = matrix_data["user_index_interaction"].get(user_id)
|
||||
# user_idx_feature = matrix_data["user_index_feature"].get(user_id)
|
||||
#
|
||||
# category_iids = matrix_data["category_to_iids"].get(category, [])
|
||||
# valid_sketch_idxs_inter = [
|
||||
# idx for iid, idx in matrix_data["sketch_index_interaction"].items()
|
||||
# if iid in category_iids
|
||||
# ]
|
||||
#
|
||||
# # 处理交互分数
|
||||
# raw_inter_scores = []
|
||||
# if user_idx_inter is not None and valid_sketch_idxs_inter:
|
||||
# raw_inter_scores = matrix_data["interaction_matrix"][user_idx_inter, valid_sketch_idxs_inter]
|
||||
# processed_inter = raw_inter_scores * 0.7
|
||||
#
|
||||
# # 处理特征分数
|
||||
# valid_sketch_idxs_feature = [
|
||||
# idx for iid, idx in matrix_data["sketch_index_feature"].items()
|
||||
# if iid in category_iids
|
||||
# ]
|
||||
# raw_feat_scores = []
|
||||
# if user_idx_feature is not None and valid_sketch_idxs_feature:
|
||||
# raw_feat_scores = matrix_data["feature_matrix"][user_idx_feature, valid_sketch_idxs_feature]
|
||||
# raw_feat_scores = (raw_feat_scores - np.min(raw_feat_scores)) / (
|
||||
# np.max(raw_feat_scores) - np.min(raw_feat_scores) + 1e-8)
|
||||
# processed_feat = raw_feat_scores
|
||||
# else:
|
||||
# processed_feat = np.array([])
|
||||
#
|
||||
# # 更新缓存
|
||||
# matrix_data["cached_scores"][cache_key] = (processed_inter, processed_feat)
|
||||
# matrix_data["cached_valid_idxs"][cache_key] = valid_sketch_idxs_inter
|
||||
#
|
||||
# # 合并分数
|
||||
# if brand_id is not None:
|
||||
# brand_idx_feature = matrix_data["brand_index_map"].get(brand_id)
|
||||
#
|
||||
# brand_feat_valid = (
|
||||
# matrix_data["brand_feature_matrix"].size > 0 and # 矩阵非空
|
||||
# brand_idx_feature is not None and
|
||||
# valid_sketch_idxs_feature # 有可用索引
|
||||
# )
|
||||
#
|
||||
# if brand_feat_valid:
|
||||
# raw_brand_feat_scores = matrix_data["brand_feature_matrix"][
|
||||
# brand_idx_feature, valid_sketch_idxs_feature
|
||||
# ]
|
||||
# raw_brand_feat_scores = (raw_brand_feat_scores - np.min(raw_brand_feat_scores)) / (
|
||||
# np.max(raw_brand_feat_scores) - np.min(raw_brand_feat_scores) + 1e-8
|
||||
# )
|
||||
# processed_brand_feat = raw_brand_feat_scores
|
||||
#
|
||||
# # 如果 processed_feat 是空的,替换为全 0,避免 shape 不一致
|
||||
# if processed_feat.size == 0:
|
||||
# processed_feat = np.zeros_like(processed_brand_feat)
|
||||
#
|
||||
# final_scores = processed_inter + 0.3 * (
|
||||
# (1 - brand_scale) * processed_feat + brand_scale * processed_brand_feat
|
||||
# )
|
||||
# else:
|
||||
# # brand 信息不可用
|
||||
# final_scores = processed_inter + 0.3 * processed_feat if processed_feat.size > 0 else processed_inter
|
||||
# else:
|
||||
# final_scores = processed_inter + 0.3 * processed_feat if processed_feat.size > 0 else processed_inter
|
||||
#
|
||||
# valid_sketch_idxs = matrix_data["cached_valid_idxs"][cache_key]
|
||||
#
|
||||
# # 概率采样
|
||||
# scores = np.array(final_scores)
|
||||
#
|
||||
# # 调整后的概率转换(带温度控制的softmax)
|
||||
# def calibrated_softmax(scores, temperature=1.0):
|
||||
# scores = scores / temperature
|
||||
# scale = scores - max(scores)
|
||||
# exps = np.exp(scale)
|
||||
# return exps / np.sum(exps)
|
||||
#
|
||||
# probs = calibrated_softmax(scores, 0.09)
|
||||
#
|
||||
# chosen_indices = np.random.choice(
|
||||
# len(valid_sketch_idxs),
|
||||
# size=min(num_recommendations, len(valid_sketch_idxs)),
|
||||
# p=probs,
|
||||
# replace=False
|
||||
# )
|
||||
# recommendations = [matrix_data["iid_to_sketch"][valid_sketch_idxs[idx]] for idx in chosen_indices]
|
||||
#
|
||||
# logger.info(f"推荐生成完成,耗时: {time.time() - start_time:.2f}秒")
|
||||
# return recommendations
|
||||
# except Exception as e:
|
||||
# logger.error(f"推荐失败: {str(e)}", exc_info=True)
|
||||
# raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
# @router.on_event("startup")
|
||||
@router.on_event("startup")
|
||||
async def startup_event():
|
||||
"""启动时初始化增量监听任务"""
|
||||
try:
|
||||
# 确保 Milvus 集合已创建(若已存在则直接返回)
|
||||
try:
|
||||
create_collection()
|
||||
except Exception as exc:
|
||||
logger.error("Milvus 集合创建/检查失败,不影响服务继续启动: %s", exc, exc_info=True)
|
||||
|
||||
# 配置定时任务
|
||||
scheduler = BackgroundScheduler()
|
||||
start_background_listener(scheduler)
|
||||
scheduler.start()
|
||||
logger.info("增量监听定时任务已启动")
|
||||
except Exception as e:
|
||||
logger.error(f"启动增量监听任务失败: {e}", exc_info=True)
|
||||
# 初始加载
|
||||
load_resources()
|
||||
|
||||
# 配置定时任务
|
||||
scheduler = BackgroundScheduler()
|
||||
scheduler.add_job(
|
||||
load_resources,
|
||||
trigger=CronTrigger(hour=0, minute=30),
|
||||
name="每日资源刷新"
|
||||
)
|
||||
scheduler.start()
|
||||
logger.info("定时任务已启动")
|
||||
|
||||
|
||||
@router.get("/recommend/{user_id}/{category}", response_model=List[str])
|
||||
async def recommend(
|
||||
user_id: int,
|
||||
category: str,
|
||||
style: Optional[str] = Query(
|
||||
None,
|
||||
description="风格样式(可选):若传入,则在利用分支对同 style 的候选进行加分",
|
||||
),
|
||||
):
|
||||
"""新版推荐接口(Milvus + Redis 偏好向量)。"""
|
||||
def softmax(scores):
|
||||
max_score = max(scores)
|
||||
exp_scores = [math.exp(s - max_score) for s in scores]
|
||||
sum_exp = sum(exp_scores)
|
||||
return [s / sum_exp for s in exp_scores]
|
||||
|
||||
|
||||
# def get_random_recommendations(category: str, num: int) -> List[str]:
|
||||
# """根据预加载热度向量推荐(冷启动)"""
|
||||
# try:
|
||||
# heat_data = matrix_data.get("heat_data", {})
|
||||
#
|
||||
# if category not in heat_data:
|
||||
# raise ValueError(f"热度数据缺少类别 {category},使用随机推荐")
|
||||
#
|
||||
# heat_dict = heat_data[category] # {url: score}
|
||||
# urls = list(heat_dict.keys())
|
||||
# scores = list(heat_dict.values())
|
||||
#
|
||||
# if not urls:
|
||||
# raise ValueError("该类别下无热度记录,使用随机推荐")
|
||||
#
|
||||
# probs = softmax(scores)
|
||||
# sample_size = min(num, len(urls))
|
||||
# sampled_urls = random.choices(urls, weights=probs, k=sample_size)
|
||||
#
|
||||
# return sampled_urls
|
||||
#
|
||||
# except Exception as e:
|
||||
# # 回退:完全随机推荐
|
||||
# all_iids = list(matrix_data["iid_to_sketch"].keys())
|
||||
# category_iids = matrix_data["category_to_iids"].get(category, all_iids)
|
||||
# sample_size = min(num, len(category_iids))
|
||||
# sampled = np.random.choice(category_iids, size=sample_size, replace=False)
|
||||
# return [matrix_data["iid_to_sketch"][iid] for iid in sampled]
|
||||
|
||||
def get_random_recommendations(category: str, num: int) -> List[str]:
|
||||
"""全品类随机推荐"""
|
||||
all_iids = list(matrix_data["iid_to_sketch"].keys())
|
||||
# 优先从当前品类选择
|
||||
category_iids = matrix_data["category_to_iids"].get(category, all_iids)
|
||||
# 确保不超出实际数量
|
||||
sample_size = min(num, len(category_iids))
|
||||
sampled = np.random.choice(category_iids, size=sample_size, replace=False)
|
||||
return [matrix_data["iid_to_sketch"][iid] for iid in sampled]
|
||||
|
||||
|
||||
@router.get("/recommend/{user_id}/{category}/{num_recommendations}/{brand_id}/{brand_scale}", response_model=List[str])
|
||||
async def get_recommendations(user_id: int, category: str, brand_id: int, brand_scale: float, num_recommendations: int = 10):
|
||||
"""
|
||||
@param user_id: 4
|
||||
@param category: female_skirt
|
||||
@param num_recommendations: 1
|
||||
@return:
|
||||
[
|
||||
"aida-sys-image/images/female/skirt/903000017.jpg"
|
||||
]
|
||||
|
||||
"""
|
||||
try:
|
||||
results = get_new_recommendations(user_id, category, style)
|
||||
path = results[0] if results else ""
|
||||
return [path]
|
||||
logger.info(f"user_id:{user_id}-----category:{category}-----brand_id:{brand_id}-----brand_scale:{brand_scale}-----num_recommendations:{num_recommendations}")
|
||||
start_time = time.time()
|
||||
cache_key = (user_id, category)
|
||||
# === 新增:用户存在性检查 ===
|
||||
user_exists_inter = user_id in matrix_data["user_index_interaction"]
|
||||
user_exists_feat = user_id in matrix_data["user_index_feature"]
|
||||
|
||||
# 任一矩阵不存在用户则返回随机推荐
|
||||
if not (user_exists_inter and user_exists_feat):
|
||||
logger.info(f"用户 {user_id} 数据不完整,触发随机推荐")
|
||||
return get_random_recommendations(category, num_recommendations)
|
||||
|
||||
# 检查缓存
|
||||
if cache_key in matrix_data["cached_scores"]:
|
||||
processed_inter, processed_feat = matrix_data["cached_scores"][cache_key]
|
||||
valid_sketch_idxs_inter = matrix_data["cached_valid_idxs"][cache_key]
|
||||
else:
|
||||
# 实时计算逻辑(同原代码)
|
||||
user_idx_inter = matrix_data["user_index_interaction"].get(user_id)
|
||||
user_idx_feature = matrix_data["user_index_feature"].get(user_id)
|
||||
|
||||
category_iids = matrix_data["category_to_iids"].get(category, [])
|
||||
valid_sketch_idxs_inter = [
|
||||
idx for iid, idx in matrix_data["sketch_index_interaction"].items()
|
||||
if iid in category_iids
|
||||
]
|
||||
|
||||
# 处理交互分数
|
||||
raw_inter_scores = []
|
||||
if user_idx_inter is not None and valid_sketch_idxs_inter:
|
||||
raw_inter_scores = matrix_data["interaction_matrix"][user_idx_inter, valid_sketch_idxs_inter]
|
||||
processed_inter = raw_inter_scores * 0.7
|
||||
|
||||
# 处理特征分数
|
||||
valid_sketch_idxs_feature = [
|
||||
idx for iid, idx in matrix_data["sketch_index_feature"].items()
|
||||
if iid in category_iids
|
||||
]
|
||||
raw_feat_scores = []
|
||||
if user_idx_feature is not None and valid_sketch_idxs_feature:
|
||||
raw_feat_scores = matrix_data["feature_matrix"][user_idx_feature, valid_sketch_idxs_feature]
|
||||
raw_feat_scores = (raw_feat_scores - np.min(raw_feat_scores)) / (
|
||||
np.max(raw_feat_scores) - np.min(raw_feat_scores) + 1e-8)
|
||||
processed_feat = raw_feat_scores
|
||||
else:
|
||||
processed_feat = np.array([])
|
||||
|
||||
# 更新缓存
|
||||
matrix_data["cached_scores"][cache_key] = (processed_inter, processed_feat)
|
||||
matrix_data["cached_valid_idxs"][cache_key] = valid_sketch_idxs_inter
|
||||
|
||||
# 合并分数
|
||||
if brand_id is not None:
|
||||
brand_idx_feature = matrix_data["brand_index_map"].get(brand_id)
|
||||
|
||||
brand_feat_valid = (
|
||||
matrix_data["brand_feature_matrix"].size > 0 and # 矩阵非空
|
||||
brand_idx_feature is not None and
|
||||
valid_sketch_idxs_feature # 有可用索引
|
||||
)
|
||||
|
||||
if brand_feat_valid:
|
||||
raw_brand_feat_scores = matrix_data["brand_feature_matrix"][
|
||||
brand_idx_feature, valid_sketch_idxs_feature
|
||||
]
|
||||
raw_brand_feat_scores = (raw_brand_feat_scores - np.min(raw_brand_feat_scores)) / (
|
||||
np.max(raw_brand_feat_scores) - np.min(raw_brand_feat_scores) + 1e-8
|
||||
)
|
||||
processed_brand_feat = raw_brand_feat_scores
|
||||
|
||||
# 如果 processed_feat 是空的,替换为全 0,避免 shape 不一致
|
||||
if processed_feat.size == 0:
|
||||
processed_feat = np.zeros_like(processed_brand_feat)
|
||||
|
||||
final_scores = processed_inter + 0.3 * (
|
||||
(1 - brand_scale) * processed_feat + brand_scale * processed_brand_feat
|
||||
)
|
||||
else:
|
||||
# brand 信息不可用
|
||||
final_scores = processed_inter + 0.3 * processed_feat if processed_feat.size > 0 else processed_inter
|
||||
else:
|
||||
final_scores = processed_inter + 0.3 * processed_feat if processed_feat.size > 0 else processed_inter
|
||||
|
||||
valid_sketch_idxs = matrix_data["cached_valid_idxs"][cache_key]
|
||||
|
||||
# 概率采样
|
||||
scores = np.array(final_scores)
|
||||
|
||||
# 调整后的概率转换(带温度控制的softmax)
|
||||
def calibrated_softmax(scores, temperature=1.0):
|
||||
scores = scores / temperature
|
||||
scale = scores - max(scores)
|
||||
exps = np.exp(scale)
|
||||
return exps / np.sum(exps)
|
||||
|
||||
probs = calibrated_softmax(scores, 0.09)
|
||||
|
||||
chosen_indices = np.random.choice(
|
||||
len(valid_sketch_idxs),
|
||||
size=min(num_recommendations, len(valid_sketch_idxs)),
|
||||
p=probs,
|
||||
replace=False
|
||||
)
|
||||
recommendations = [matrix_data["iid_to_sketch"][valid_sketch_idxs[idx]] for idx in chosen_indices]
|
||||
|
||||
logger.info(f"推荐生成完成,耗时: {time.time() - start_time:.2f}秒")
|
||||
return recommendations
|
||||
|
||||
except Exception as e:
|
||||
logger.error("新版推荐接口失败 [user=%s, category=%s]: %s", user_id, category, e, exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
logger.error(f"推荐失败: {str(e)}", exc_info=True)
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@@ -1,42 +1,40 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.api import api_attribute_retrieve, api_query_image
|
||||
from app.api import api_attribute_retrieve
|
||||
from app.api import api_brand_dna
|
||||
from app.api import api_brighten
|
||||
from app.api import api_chat_robot
|
||||
from app.api import api_clothing_seg
|
||||
from app.api import api_design
|
||||
from app.api import api_design_pre_processing
|
||||
from app.api import api_extraction_project_info
|
||||
from app.api import api_generate_image
|
||||
from app.api import api_image2sketch
|
||||
from app.api import api_import_sys_sketch
|
||||
from app.api import api_mannequins_edit
|
||||
from app.api import api_pose_transform
|
||||
from app.api import api_precompute
|
||||
from app.api import api_prompt_generation
|
||||
from app.api import api_recommendation
|
||||
from app.api import api_super_resolution
|
||||
from app.api import api_test
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
router.include_router(api_test.router, tags=["test"], prefix="/test")
|
||||
router.include_router(api_super_resolution.router, tags=["super_resolution"], prefix="/api")
|
||||
router.include_router(api_generate_image.router, tags=["generate_image"], prefix="/api")
|
||||
router.include_router(api_attribute_retrieve.router, tags=["attribute_retrieve"], prefix="/api")
|
||||
router.include_router(api_design.router, tags=['design'], prefix="/api")
|
||||
router.include_router(api_chat_robot.router, tags=['chat_robot'], prefix="/api")
|
||||
router.include_router(api_prompt_generation.router, tags=['prompt_generation'], prefix="/api")
|
||||
router.include_router(api_design_pre_processing.router, tags=['design_pre_processing'], prefix="/api")
|
||||
router.include_router(api_image2sketch.router, tags=['api_image2sketch'], prefix="/api")
|
||||
router.include_router(api_brighten.router, tags=['api_brighten'], prefix="/api")
|
||||
router.include_router(api_query_image.router, tags=['api_query_image'], prefix="/api")
|
||||
router.include_router(api_brand_dna.router, tags=['api_brand_dna'], prefix="/api")
|
||||
router.include_router(api_recommendation.router, tags=['api_recommendation'], prefix="/api")
|
||||
router.include_router(api_mannequins_edit.router, tags=['api_mannequins_edit'], prefix="/api")
|
||||
router.include_router(api_pose_transform.router, tags=['api_pose_transform'], prefix="/api")
|
||||
router.include_router(api_clothing_seg.router, tags=['api_clothing_seg'], prefix="/api")
|
||||
router.include_router(api_extraction_project_info.router, tags=['api_extraction_project_info'], prefix="/api")
|
||||
router.include_router(api_import_sys_sketch.router, tags=['api_import_sys_sketch'], prefix="/api")
|
||||
router.include_router(api_precompute.router, tags=['api_precompute'], prefix="/api")
|
||||
|
||||
"""停用"""
|
||||
# from app.api import api_chat_robot
|
||||
# from app.api import api_query_image
|
||||
# from app.api import api_brighten
|
||||
# from app.api import api_extraction_project_info
|
||||
# from app.api import api_image2sketch
|
||||
# from app.api import api_super_resolution
|
||||
# router.include_router(api_image2sketch.router, tags=['api_image2sketch'], prefix="/api")
|
||||
# router.include_router(api_query_image.router, tags=['api_query_image'], prefix="/api")
|
||||
# router.include_router(api_chat_robot.router, tags=['chat_robot'], prefix="/api")
|
||||
# router.include_router(api_super_resolution.router, tags=["super_resolution"], prefix="/api")
|
||||
# router.include_router(api_brighten.router, tags=['api_brighten'], prefix="/api")
|
||||
# router.include_router(api_extraction_project_info.router, tags=['api_extraction_project_info'], prefix="/api")
|
||||
|
||||
@@ -27,7 +27,7 @@ def super_resolution(request_item: SuperResolutionModel, background_tasks: Backg
|
||||
}
|
||||
"""
|
||||
try:
|
||||
logger.info(f"super_resolution request item is : @@@@@@:{json.dumps(request_item.dict())}")
|
||||
logger.info(f"super_resolution request item is : @@@@@@:{json.dumps(request_item.dict(),indent=4)}")
|
||||
service = SuperResolution(request_item)
|
||||
background_tasks.add_task(service.sr_result)
|
||||
except Exception as e:
|
||||
|
||||
@@ -4,8 +4,7 @@ import logging
|
||||
from fastapi import APIRouter
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.core.config import SR_RABBITMQ_QUEUES, GI_RABBITMQ_QUEUES, GPI_RABBITMQ_QUEUES, GRI_RABBITMQ_QUEUES, OSS, JAVA_STREAM_API_URL, GMV_RABBITMQ_QUEUES, SLOGAN_RABBITMQ_QUEUES, GEN_SINGLE_LOGO_RABBITMQ_QUEUES, PS_RABBITMQ_QUEUES, BATCH_GPI_RABBITMQ_QUEUES, BATCH_GRI_RABBITMQ_QUEUES, \
|
||||
BATCH_PS_RABBITMQ_QUEUES, RABBITMQ_ENV
|
||||
from app.core.config import settings, SR_RABBITMQ_QUEUES, GMV_RABBITMQ_QUEUES, PS_RABBITMQ_QUEUES, SLOGAN_RABBITMQ_QUEUES, GI_RABBITMQ_QUEUES, GPI_RABBITMQ_QUEUES, GRI_RABBITMQ_QUEUES, BATCH_GPI_RABBITMQ_QUEUES, BATCH_GRI_RABBITMQ_QUEUES, BATCH_PS_RABBITMQ_QUEUES
|
||||
from app.schemas.response_template import ResponseModel
|
||||
|
||||
logger = logging.getLogger()
|
||||
@@ -15,9 +14,9 @@ router = APIRouter()
|
||||
@router.get("{id}")
|
||||
def test(id: int):
|
||||
data = {
|
||||
"RABBITMQ_ENV":RABBITMQ_ENV,
|
||||
"超分 SR_RABBITMQ_QUEUES": SR_RABBITMQ_QUEUES,
|
||||
"多视角 GMV_RABBITMQ_QUEUES": GMV_RABBITMQ_QUEUES,
|
||||
"RABBITMQ_ENV": settings.SERVE_ENV,
|
||||
# "超分 SR_RABBITMQ_QUEUES": SR_RABBITMQ_QUEUES,
|
||||
# "多视角 GMV_RABBITMQ_QUEUES": GMV_RABBITMQ_QUEUES,
|
||||
"pose transform PS_RABBITMQ_QUEUES": PS_RABBITMQ_QUEUES,
|
||||
"logan SLOGAN_RABBITMQ_QUEUES": SLOGAN_RABBITMQ_QUEUES,
|
||||
"image and single logo GI_RABBITMQ_QUEUES": GI_RABBITMQ_QUEUES,
|
||||
@@ -29,10 +28,9 @@ def test(id: int):
|
||||
"batch relight BATCH_GRI_RABBITMQ_QUEUES": BATCH_GRI_RABBITMQ_QUEUES,
|
||||
"batch pose transform BATCH_PS_RABBITMQ_QUEUES": BATCH_PS_RABBITMQ_QUEUES,
|
||||
|
||||
"JAVA_STREAM_API_URL": JAVA_STREAM_API_URL,
|
||||
"local_oss_server": OSS
|
||||
"JAVA_STREAM_API_URL": settings.JAVA_STREAM_API_URL,
|
||||
}
|
||||
logger.info(json.dumps(data))
|
||||
logger.info(json.dumps(data, ensure_ascii=False, indent=4))
|
||||
if id == 1:
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user