This commit is contained in:
jeremygan2021
2026-02-17 12:14:27 +08:00
parent 4659802f7a
commit a4475e743d
3 changed files with 52 additions and 10 deletions

View File

@@ -70,7 +70,8 @@ HISTORY_FILE = "history.json"
# Dashscope (Qwen-VL) 配置 # Dashscope (Qwen-VL) 配置
dashscope.api_key = 'sk-ce2404f55f744a1987d5ece61c6bac58' dashscope.api_key = 'sk-ce2404f55f744a1987d5ece61c6bac58'
QWEN_MODEL = 'qwen-vl-max' QWEN_MODEL = 'qwen-vl-max' # Default model
AVAILABLE_QWEN_MODELS = ["qwen-vl-max", "qwen-vl-plus"]
# API Tags (用于文档分类) # API Tags (用于文档分类)
TAG_GENERAL = "General Segmentation (通用分割)" TAG_GENERAL = "General Segmentation (通用分割)"
@@ -1019,7 +1020,8 @@ async def segment_face(
processor=processor, processor=processor,
image=image, image=image,
prompt=final_prompt, prompt=final_prompt,
output_base_dir=RESULT_IMAGE_DIR output_base_dir=RESULT_IMAGE_DIR,
qwen_model=QWEN_MODEL
) )
except Exception as e: except Exception as e:
import traceback import traceback
@@ -1222,9 +1224,23 @@ async def get_config(request: Request):
"device": device, "device": device,
"cleanup_enabled": os.getenv("AUTO_CLEANUP_ENABLED"), "cleanup_enabled": os.getenv("AUTO_CLEANUP_ENABLED"),
"file_lifetime": os.getenv("FILE_LIFETIME_SECONDS"), "file_lifetime": os.getenv("FILE_LIFETIME_SECONDS"),
"cleanup_interval": os.getenv("CLEANUP_INTERVAL_SECONDS") "cleanup_interval": os.getenv("CLEANUP_INTERVAL_SECONDS"),
"current_qwen_model": QWEN_MODEL,
"available_qwen_models": AVAILABLE_QWEN_MODELS
} }
@app.post("/admin/api/config/model", dependencies=[Depends(verify_admin)])
async def set_model(model: str = Form(...)):
"""
Set the Qwen model
"""
global QWEN_MODEL
if model not in AVAILABLE_QWEN_MODELS:
raise HTTPException(status_code=400, detail="Invalid model")
QWEN_MODEL = model
return {"status": "success", "message": f"Model switched to {model}", "current_model": QWEN_MODEL}
# ========================================== # ==========================================
# 10. Main Entry Point (启动入口) # 10. Main Entry Point (启动入口)
# ========================================== # ==========================================

View File

@@ -95,7 +95,7 @@ def create_highlighted_visualization(image: Image.Image, masks, output_path: str
# Save # Save
Image.fromarray(result_np).save(output_path) Image.fromarray(result_np).save(output_path)
def analyze_demographics_with_qwen(image_path: str) -> dict: def analyze_demographics_with_qwen(image_path: str, model_name: str = 'qwen-vl-max') -> dict:
""" """
调用 Qwen-VL 模型分析人物的年龄和性别 调用 Qwen-VL 模型分析人物的年龄和性别
""" """
@@ -122,7 +122,7 @@ def analyze_demographics_with_qwen(image_path: str) -> dict:
] ]
# 调用模型 # 调用模型
response = MultiModalConversation.call(model=QWEN_MODEL, messages=messages) response = MultiModalConversation.call(model=model_name, messages=messages)
if response.status_code == 200: if response.status_code == 200:
content = response.output.choices[0].message.content[0]['text'] content = response.output.choices[0].message.content[0]['text']
@@ -143,7 +143,8 @@ def process_face_segmentation_and_analysis(
processor, processor,
image: Image.Image, image: Image.Image,
prompt: str = "head", prompt: str = "head",
output_base_dir: str = "static/results" output_base_dir: str = "static/results",
qwen_model: str = "qwen-vl-max"
) -> dict: ) -> dict:
""" """
核心处理逻辑: 核心处理逻辑:
@@ -208,7 +209,7 @@ def process_face_segmentation_and_analysis(
cropped_img.save(save_path) cropped_img.save(save_path)
# 3. 识别 # 3. 识别
analysis = analyze_demographics_with_qwen(save_path) analysis = analyze_demographics_with_qwen(save_path, model_name=qwen_model)
# 构造返回结果 # 构造返回结果
# 注意URL 生成需要依赖外部的 request context这里只返回相对路径或文件名 # 注意URL 生成需要依赖外部的 request context这里只返回相对路径或文件名

View File

@@ -200,9 +200,15 @@
<span class="text-gray-600">模型</span> <span class="text-gray-600">模型</span>
<span class="font-mono">SAM3</span> <span class="font-mono">SAM3</span>
</div> </div>
<div class="flex justify-between border-b pb-2"> <div class="flex justify-between items-center border-b pb-2">
<span class="text-gray-600">多模态模型</span> <span class="text-gray-600">多模态模型</span>
<span class="font-mono">Qwen-VL-Max</span> <div class="flex items-center gap-2">
<select v-model="currentModel" @change="updateModel" class="border rounded px-2 py-1 text-sm font-mono bg-white">
<option v-for="model in availableModels" :key="model" :value="model">
{{ model }}
</option>
</select>
</div>
</div> </div>
<div class="flex justify-between border-b pb-2"> <div class="flex justify-between border-b pb-2">
<span class="text-gray-600">设备</span> <span class="text-gray-600">设备</span>
@@ -239,6 +245,8 @@
const previewUrl = ref(null); const previewUrl = ref(null);
const cleaning = ref(false); const cleaning = ref(false);
const deviceInfo = ref('Loading...'); const deviceInfo = ref('Loading...');
const currentModel = ref('');
const availableModels = ref([]);
// 检查登录状态 // 检查登录状态
const checkLogin = () => { const checkLogin = () => {
@@ -296,11 +304,27 @@
try { try {
const res = await axios.get('/admin/api/config'); const res = await axios.get('/admin/api/config');
deviceInfo.value = res.data.device; deviceInfo.value = res.data.device;
currentModel.value = res.data.current_qwen_model;
availableModels.value = res.data.available_qwen_models;
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
}; };
const updateModel = async () => {
try {
const formData = new FormData();
formData.append('model', currentModel.value);
const res = await axios.post('/admin/api/config/model', formData);
alert(res.data.message);
} catch (e) {
alert('更新模型失败');
console.error(e);
// Revert on failure
fetchSystemInfo();
}
};
const enterDir = (dirName) => { const enterDir = (dirName) => {
currentPath.value = currentPath.value ? `${currentPath.value}/${dirName}` : dirName; currentPath.value = currentPath.value ? `${currentPath.value}/${dirName}` : dirName;
fetchFiles(); fetchFiles();
@@ -390,7 +414,8 @@
currentTab, history, files, currentPath, currentTab, history, files, currentPath,
enterDir, navigateUp, deleteFile, triggerCleanup, enterDir, navigateUp, deleteFile, triggerCleanup,
viewResult, previewImage, isImage, previewUrl, viewResult, previewImage, isImage, previewUrl,
formatDate, getTypeBadgeClass, cleaning, deviceInfo formatDate, getTypeBadgeClass, cleaning, deviceInfo,
currentModel, availableModels, updateModel
}; };
} }
}).mount('#app'); }).mount('#app');