Compare commits

...

4 Commits

Author SHA1 Message Date
build-ops d6f39c18a5 test(vision): update wiring tests for V2 batch analyze_images_v2 path
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m23s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 14s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m56s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m18s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 6m51s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 10m24s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m50s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 13m3s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m56s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 13m41s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 27m24s
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 38s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m48s
2026-10-05 19:47:59 +08:00
build-ops 7843b92ef8 style(vision): rename ambiguous l/r vars to lb/rb (ruff E741)
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 54s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m45s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m19s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m2s
AI Code Review / AI Code Review (pull_request) Successful in 7m3s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 10m3s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 11m0s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 12m44s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m45s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 17m30s
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
2026-10-05 19:22:03 +08:00
CI Bot 12f74b8d52 style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m2s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m13s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m48s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m21s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m0s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 4m18s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 5m0s
AI Code Review / AI Code Review (pull_request) Successful in 7m7s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 10m25s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 12m4s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 2s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 8m53s
2026-10-05 11:11:29 +00:00
xiaoxia cdd343131e fix(vision): #2205 thinking参数互斥修复——只传thinking=disabled,去掉reasoning_effort
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m10s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m52s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m59s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m58s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 4m8s
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
根因:上版同时传 thinking={type:disabled} + reasoning_effort=low,方舟返回400
Invalid combination of reasoning_effort and thinking type。降级重试分支
把两个参数都pop掉,模型回到默认thinking开启→响应9-12s超时,fast全败。

修复:
1. 只传 thinking={"type":"disabled"},去掉互斥的 reasoning_effort
2. 400降级只pop thinking,保留精简payload重试(不pop多个)
3. 先单独验证 lite 单次HTTP 200且reasoning_tokens=0再跑E2E,省一轮部署
2026-10-05 19:06:02 +08:00
3 changed files with 50 additions and 42 deletions
@@ -187,10 +187,10 @@ def call_pro_vlm(
return None
text = _strip_code_fence(raw)
l, r = text.find("{"), text.rfind("}")
if l >= 0 and r > l:
lb, rb = text.find("{"), text.rfind("}")
if lb >= 0 and rb > lb:
try:
obj = json.loads(text[l : r + 1])
obj = json.loads(text[lb : rb + 1])
if isinstance(obj, dict):
logger.info("[vision.vlm] 图片 #%d pro VLM JSON 完成 elapsed=%.1fs", idx, elapsed)
return {
@@ -117,14 +117,9 @@ def call_fast_json(
"max_tokens": max_tokens,
"stream": False,
}
# 关键:关闭 thinking(避免产生 reasoning_tokens 拖慢响应)
# 方舟/豆包 2.x 模型支持 thinking.type=disabled
try:
payload["thinking"] = {"type": "disabled"}
except Exception:
pass
# 部分模型用 reasoning_effort 控制思考深度
payload["reasoning_effort"] = "low"
# 关键:关闭 thinking(reasoning_tokens 是延迟主因,单次要10-12s)
# 方舟/豆包 Seed 2.x 支持 thinking={type:"disabled"},且不要和 reasoning_effort 同时传(两者互斥会400)
payload["thinking"] = {"type": "disabled"}
resp = httpx.post(
url,
@@ -133,15 +128,12 @@ def call_fast_json(
timeout=timeout,
)
elapsed = time.time() - t0
if resp.status_code != 200:
logger.warning(
"[vision.v2] fast_json HTTP %d elapsed=%.1fs body=%s", resp.status_code, elapsed, resp.text[:200]
)
# 如果400说明不支持thinking参数,降级重试一次
if resp.status_code == 400 and "thinking" in resp.text.lower():
# 400 说明模型不支持 thinking 参数(极少数旧模型),重试一次不带 thinking
if resp.status_code == 400:
body_preview = resp.text[:300].lower()
logger.warning("[vision.v2] fast_json HTTP 400 elapsed=%.1fs body=%s", elapsed, resp.text[:200])
if "thinking" in body_preview or "reasoning" in body_preview:
payload.pop("thinking", None)
payload.pop("reasoning_effort", None)
time.time()
resp = httpx.post(
url,
headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
@@ -150,10 +142,15 @@ def call_fast_json(
)
elapsed = time.time() - t0
if resp.status_code != 200:
logger.warning("[vision.v2] fast_json 降级后 HTTP %d elapsed=%.1fs", resp.status_code, elapsed)
logger.warning("[vision.v2] fast_json 降级重试 HTTP %d elapsed=%.1fs", resp.status_code, elapsed)
return None
else:
return None
elif resp.status_code != 200:
logger.warning(
"[vision.v2] fast_json HTTP %d elapsed=%.1fs body=%s", resp.status_code, elapsed, resp.text[:200]
)
return None
data = resp.json()
raw = (data.get("choices") or [{}])[0].get("message", {}).get("content")
if raw is None:
@@ -175,10 +172,10 @@ def call_fast_json(
text = _strip_code_fence(raw)
# 截到第一个 { 和最后一个 } 之间,容忍前后偶发文字
l = text.find("{")
r = text.rfind("}")
if l >= 0 and r > l:
text = text[l : r + 1]
lb = text.find("{")
rb = text.rfind("}")
if lb >= 0 and rb > lb:
text = text[lb : rb + 1]
try:
obj = json.loads(text)
except json.JSONDecodeError:
+29 -18
View File
@@ -97,21 +97,28 @@ def invalidate_loader_cache():
class TestImageAnalysisWiring:
def test_uses_loader_template_and_xml_parse(self, job):
def test_v2_batch_analysis_returns_products(self, job):
"""V2 路径:_step_image_analysis 批量调用 analyze_images_v2,返回 products。"""
from apps.worker.worker_app.tasks import viral_video as vv
with patch("packages.shared.ai_service.call_vision", return_value=IMAGE_XML) as mock_v:
result = vv._analyze_single_image(0, "https://img/1.jpg", "vlm-lite", 15)
fake_product = {
"name": "lipstick",
"brand": "品牌X",
"category": "唇部彩妆",
"key_features": ["显白", "持久"],
"text_on_package": ["品牌X", "211"],
"_source": "v2_fast_json",
}
with patch("worker_app.tasks.vision.analyze_images_v2", return_value=[fake_product]) as mock_aiv2:
result = vv._step_image_analysis(job)
mock_v.assert_called_once()
# 验证调用时传入了 system_prompt(说明走了 loader 渲染的模板)
call_kwargs = mock_v.call_args.kwargs
assert "system_prompt" in call_kwargs and call_kwargs["system_prompt"]
# 结果包含从 XML 解析出的产品信息
assert result["name"] == "lipstick"
assert result["brand"] == "品牌X"
assert "显白" in result["key_features"]
assert result["text_on_package"] == ["品牌X", "211"]
mock_aiv2.assert_called_once()
products = result["products"]
assert len(products) == 1
assert products[0]["name"] == "lipstick"
assert products[0]["brand"] == "品牌X"
assert "显白" in products[0]["key_features"]
assert products[0]["text_on_package"] == ["品牌X", "211"]
# ── 2) 意图解析走模板 ───────────────────────────────────────────────
@@ -252,18 +259,22 @@ class TestEndToEndLoaderUsed:
called_types.append(prompt_type)
return real_get(prompt_type, **kwargs)
# V2 图片分析不再走 prompt_loader(固定 lite JSON prompt),用 mock 产品代替
img_res = {
"name": "lipstick",
"brand": "品牌X",
"key_features": ["显白", "持久"],
"text_on_package": ["品牌X"],
}
with (
patch.object(pl, "get_template", side_effect=spy_get),
patch("packages.shared.ai_service.call_vision", return_value=IMAGE_XML),
patch("packages.shared.ai_service.call_llm", return_value=INTENT_XML),
):
# 1) image
img_res = vv._analyze_single_image(0, "https://img/1.jpg", "vlm", 15)
# 2) intent
# intent
intent_res = vv._step_intent_parsing(job, {"products": [img_res]})
# 前两步分别调用了 image_analysis 和 intent_parsing
assert "image_analysis" in called_types
# V2 图片分析走固定 prompt(不经 loader);intent 仍走 loader
assert "image_analysis" not in called_types
assert "intent_parsing" in called_types
# script 和 review 单独验证(需要不同的 LLM 返回)