增加多模态模型识别功能,可以正确显示置信度了。
This commit is contained in:
@@ -1,10 +1,39 @@
|
|||||||
import json
|
import json
|
||||||
|
import re
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
from .ollama_client import chat_vision
|
from .ollama_client import chat_vision
|
||||||
from .prompts import build_closedset_prompt
|
from .prompts import build_closedset_prompt
|
||||||
|
|
||||||
|
|
||||||
|
def _extract_json_obj(text: str):
|
||||||
|
"""尽量从返回文本中提取出合法 JSON(支持代码块/前后说明)。"""
|
||||||
|
if not isinstance(text, str):
|
||||||
|
return None
|
||||||
|
s = text.strip()
|
||||||
|
# 去掉 Markdown 代码块包裹
|
||||||
|
if s.startswith("```"):
|
||||||
|
s = re.sub(r"^```[a-zA-Z]*\n|\n```$", "", s).strip()
|
||||||
|
# 直接解析
|
||||||
|
try:
|
||||||
|
obj = json.loads(s)
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
return obj
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
# 提取第一个花括号对象
|
||||||
|
m = re.search(r"\{[\s\S]*?\}", s)
|
||||||
|
if m:
|
||||||
|
frag = m.group(0)
|
||||||
|
try:
|
||||||
|
obj = json.loads(frag)
|
||||||
|
if isinstance(obj, dict):
|
||||||
|
return obj
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def classify_image(
|
def classify_image(
|
||||||
image_path: str,
|
image_path: str,
|
||||||
labels: List[str],
|
labels: List[str],
|
||||||
@@ -25,15 +54,14 @@ def classify_image(
|
|||||||
|
|
||||||
print("[VLM] Calling chat_vision...")
|
print("[VLM] Calling chat_vision...")
|
||||||
text = chat_vision(prompt, [image_path], temperature=0.1)
|
text = chat_vision(prompt, [image_path], temperature=0.1)
|
||||||
_preview_text = (text[:120]).replace("\n", " ")
|
_preview_text = (str(text)[:200]).replace("\n", " ")
|
||||||
print(f"[VLM] Received text length={len(text)} preview={_preview_text}...")
|
print(f"[VLM] Received text length={len(str(text))} preview={_preview_text}...")
|
||||||
|
|
||||||
# 主路径:严格 JSON 解析
|
# 解析 JSON(更健壮)
|
||||||
try:
|
obj = _extract_json_obj(str(text))
|
||||||
obj = json.loads(text)
|
if obj and "label" in obj:
|
||||||
if isinstance(obj, dict) and "label" in obj:
|
|
||||||
label = obj.get("label", "")
|
label = obj.get("label", "")
|
||||||
# 纠偏:若输出不在封闭集,尝试包含匹配;否则 Unknown
|
# 若输出不在封闭集,尝试包含匹配;否则 Unknown
|
||||||
if label not in labels:
|
if label not in labels:
|
||||||
for lb in labels:
|
for lb in labels:
|
||||||
if lb in str(label):
|
if lb in str(label):
|
||||||
@@ -49,14 +77,14 @@ def classify_image(
|
|||||||
result = {"label": label, "confidence": conf}
|
result = {"label": label, "confidence": conf}
|
||||||
print(f"[VLM] Parsed JSON result={result}")
|
print(f"[VLM] Parsed JSON result={result}")
|
||||||
return result
|
return result
|
||||||
except Exception as e:
|
|
||||||
print(f"[VLM] JSON parse failed: {e}")
|
|
||||||
|
|
||||||
# 回退:字符串包含匹配
|
print("[VLM] JSON parse failed or missing 'label', enter fallback")
|
||||||
|
|
||||||
|
# 回退:字符串包含匹配(无法确定置信度时返回 0.0)
|
||||||
for lb in labels:
|
for lb in labels:
|
||||||
if lb in text:
|
if lb in str(text):
|
||||||
print(f"[VLM] Fallback match label={lb}")
|
print(f"[VLM] Fallback match label={lb}")
|
||||||
return {"label": lb, "confidence": 0.5}
|
return {"label": lb, "confidence": 0.0}
|
||||||
|
|
||||||
print("[VLM] No match, return Unknown")
|
print("[VLM] No match, return Unknown")
|
||||||
return {"label": "Unknown", "confidence": 0.0}
|
return {"label": "Unknown", "confidence": 0.0}
|
||||||
|
|||||||
Reference in New Issue
Block a user