fix code
This commit is contained in:
@@ -2,12 +2,15 @@ import asyncio
|
||||
from typing import Dict, Any, List
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
import hashlib
|
||||
from dashscope import MultiModalConversation
|
||||
from backend.app.admin.service.file_service import file_service
|
||||
from langchain_core.messages import SystemMessage, HumanMessage
|
||||
from backend.core.llm import LLMFactory, AuditLogCallbackHandler
|
||||
from backend.core.conf import settings
|
||||
from backend.core.prompts.scene_variation import get_scene_variation_prompt
|
||||
from backend.database.redis import redis_client
|
||||
|
||||
class SceneVariationGenerator:
|
||||
"""
|
||||
@@ -86,6 +89,59 @@ class SceneVariationGenerator:
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
|
||||
class QwenImageKeyManager:
|
||||
RATE_LIMIT_PER_SECOND = 2
|
||||
WINDOW_SECONDS = 1
|
||||
REDIS_PREFIX = "qwen:image_edit:rate"
|
||||
|
||||
@classmethod
|
||||
def _get_keys(cls) -> List[str]:
|
||||
raw = settings.QWEN_API_KEY or ""
|
||||
if not raw:
|
||||
raw = os.getenv("DASHSCOPE_API_KEY") or ""
|
||||
parts = [p.strip() for p in raw.split(";") if p.strip()]
|
||||
if parts:
|
||||
return parts
|
||||
if raw:
|
||||
return [raw]
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def _key_id(cls, key: str) -> str:
|
||||
return hashlib.sha256(key.encode()).hexdigest()[:16]
|
||||
|
||||
@classmethod
|
||||
async def acquire_key(cls) -> str:
|
||||
keys = cls._get_keys()
|
||||
if not keys:
|
||||
raise Exception("Qwen API key not configured")
|
||||
now = int(time.time())
|
||||
n = len(keys)
|
||||
start = now % n
|
||||
for i in range(n):
|
||||
key = keys[(start + i) % n]
|
||||
kid = cls._key_id(key)
|
||||
redis_key = f"{cls.REDIS_PREFIX}:{kid}:{now}"
|
||||
count = await redis_client.incr(redis_key)
|
||||
if count == 1:
|
||||
await redis_client.expire(redis_key, cls.WINDOW_SECONDS + 1)
|
||||
if count <= cls.RATE_LIMIT_PER_SECOND:
|
||||
return key
|
||||
await asyncio.sleep(1.0 / cls.RATE_LIMIT_PER_SECOND)
|
||||
now2 = int(time.time())
|
||||
for i in range(n):
|
||||
key = keys[(start + i) % n]
|
||||
kid = cls._key_id(key)
|
||||
redis_key = f"{cls.REDIS_PREFIX}:{kid}:{now2}"
|
||||
count = await redis_client.incr(redis_key)
|
||||
if count == 1:
|
||||
await redis_client.expire(redis_key, cls.WINDOW_SECONDS + 1)
|
||||
if count <= cls.RATE_LIMIT_PER_SECOND:
|
||||
return key
|
||||
raise Exception("Qwen image edit rate limited")
|
||||
|
||||
|
||||
class Illustrator:
|
||||
"""
|
||||
Component for generating edited images based on text descriptions (Step 2 of the advanced workflow).
|
||||
@@ -116,11 +172,14 @@ class Illustrator:
|
||||
]
|
||||
|
||||
try:
|
||||
# Wrap the blocking SDK call in asyncio.to_thread
|
||||
if api_key:
|
||||
final_api_key = api_key
|
||||
else:
|
||||
final_api_key = await QwenImageKeyManager.acquire_key()
|
||||
response = await asyncio.to_thread(
|
||||
MultiModalConversation.call,
|
||||
api_key=api_key or os.getenv("DASHSCOPE_API_KEY") or settings.QWEN_API_KEY,
|
||||
model="qwen-image-edit-plus", # Assuming this is the model name for image editing
|
||||
api_key=final_api_key,
|
||||
model="qwen-image-edit-plus",
|
||||
messages=messages,
|
||||
stream=False,
|
||||
n=1,
|
||||
|
||||
@@ -12,6 +12,15 @@ from backend.app.admin.service.audit_log_service import audit_log_service
|
||||
from backend.core.conf import settings
|
||||
from backend.common.log import log as logger
|
||||
|
||||
|
||||
def _get_primary_qwen_api_key() -> str:
|
||||
raw = settings.QWEN_API_KEY or ""
|
||||
parts = [p.strip() for p in raw.split(";") if p.strip()]
|
||||
if parts:
|
||||
return parts[0]
|
||||
return raw
|
||||
|
||||
|
||||
class AuditLogCallbackHandler(BaseCallbackHandler):
|
||||
def __init__(self, metadata: Optional[Dict[str, Any]] = None):
|
||||
super().__init__()
|
||||
@@ -99,7 +108,7 @@ class LLMFactory:
|
||||
|
||||
if model_type == 'qwen':
|
||||
return ChatTongyi(
|
||||
api_key=settings.QWEN_API_KEY,
|
||||
api_key=_get_primary_qwen_api_key(),
|
||||
model_name=settings.QWEN_TEXT_MODEL,
|
||||
**kwargs
|
||||
)
|
||||
@@ -110,10 +119,9 @@ class LLMFactory:
|
||||
**kwargs
|
||||
)
|
||||
else:
|
||||
# Default to Qwen if unknown
|
||||
logger.warning(f"Unknown model type {model_type}, defaulting to Qwen")
|
||||
return ChatTongyi(
|
||||
api_key=settings.QWEN_API_KEY,
|
||||
api_key=_get_primary_qwen_api_key(),
|
||||
model_name=settings.QWEN_TEXT_MODEL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@@ -23,6 +23,14 @@ from sqlalchemy.exc import IntegrityError
|
||||
from asyncio import sleep
|
||||
|
||||
|
||||
def _get_primary_qwen_api_key() -> str:
|
||||
raw = settings.QWEN_API_KEY or ""
|
||||
parts = [p.strip() for p in raw.split(";") if p.strip()]
|
||||
if parts:
|
||||
return parts[0]
|
||||
return raw
|
||||
|
||||
|
||||
class Qwen:
|
||||
# 创建一个类级别的线程池执行器
|
||||
_executor = ThreadPoolExecutor(max_workers=10)
|
||||
@@ -33,7 +41,7 @@ class Qwen:
|
||||
|
||||
@staticmethod
|
||||
async def text_to_speak(content: str, image_text_id: int | None = None, image_id: int | None = None, user_id: int | None = None, ref_type: str | None = None, ref_id: int | None = None) -> Dict[str, Any]:
|
||||
api_key = settings.QWEN_API_KEY
|
||||
api_key = _get_primary_qwen_api_key()
|
||||
model_name = "qwen3-tts-flash"
|
||||
voice = "Jennifer"
|
||||
language_type = "English"
|
||||
@@ -185,7 +193,7 @@ class Qwen:
|
||||
|
||||
@staticmethod
|
||||
async def chat(messages: List[Dict[str, str]], image_id: int = 0, user_id: int = 0, api_type: str = "chat") -> Dict[str, Any]:
|
||||
api_key = settings.QWEN_API_KEY
|
||||
api_key = _get_primary_qwen_api_key()
|
||||
model_name = settings.QWEN_TEXT_MODEL
|
||||
start_time = time.time()
|
||||
start_at = datetime.now()
|
||||
@@ -314,7 +322,7 @@ class Qwen:
|
||||
"""通用API调用方法"""
|
||||
|
||||
model_name = ""
|
||||
api_key = settings.QWEN_API_KEY
|
||||
api_key = _get_primary_qwen_api_key()
|
||||
response = None
|
||||
start_time = time.time()
|
||||
start_at = datetime.now()
|
||||
@@ -481,7 +489,7 @@ class Qwen:
|
||||
# 轮询任务状态
|
||||
start_time = time.time()
|
||||
headers = {
|
||||
"Authorization": f"Bearer {settings.QWEN_API_KEY}",
|
||||
"Authorization": f"Bearer {_get_primary_qwen_api_key()}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user