readme
This commit is contained in:
@@ -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 (启动入口)
|
||||||
# ==========================================
|
# ==========================================
|
||||||
|
|||||||
@@ -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,这里只返回相对路径或文件名
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|||||||
Reference in New Issue
Block a user