feat : 代码梳理 移除所有敏感密钥 通过环境变量方式配置
All checks were successful
git commit AiDA python develop 分支构建部署 / scheduled_deploy (push) Has been skipped

This commit is contained in:
zcr
2025-12-30 16:49:08 +08:00
parent 1be716e414
commit 18024a2d70
167 changed files with 5283 additions and 10464 deletions

View File

@@ -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))

View File

@@ -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。
创建一个具有以下参数的请求体:

View File

@@ -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()
# 触发计算并持久化,若内部出错会抛异常

View File

@@ -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:

View File

@@ -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))

View File

@@ -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:

View File

@@ -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)

View File

@@ -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))

View File

@@ -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)

View File

@@ -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:

View File

@@ -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"]
}
)

View File

@@ -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))

View File

@@ -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 = {}

View File

@@ -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"]
}
)

View File

@@ -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

View File

@@ -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))

View File

@@ -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))

View File

@@ -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")

View File

@@ -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:

View File

@@ -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")