mirror of
https://github.com/primedigitaltech/market-assistant.git
synced 2026-07-21 23:41:39 +08:00
移除 crawler_copy/jd_pc_search/AI_crawler.py;试跑与校验逻辑在 openai_gateway/__main__.py。更新 README 与 .env.example 说明。 Made-with: Cursor
110 lines
3.4 KiB
Python
110 lines
3.4 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
命令行单图配料表试跑(多模态)。实现位于本包,**非**对其它模块的再导出。
|
||
|
||
在 ``backend`` 目录下执行::
|
||
|
||
.venv\\Scripts\\python.exe -m pipeline.openai_gateway
|
||
|
||
与 Django 一样从**仓库根** ``.env`` 读取 ``OPENAI_*`` / ``LLM_*``。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
from typing import Any
|
||
|
||
# 与 ingredients_defaults 同口径;可在此改图 URL/路径
|
||
IMAGE_SOURCE = "https://img30.360buyimg.com/sku/jfs/t1/390444/8/13018/103574/6982e951Fc44d9d7b/00d62ee56189d75d.jpg.avif"
|
||
|
||
_HERE = Path(__file__).resolve()
|
||
# openai_gateway -> pipeline -> backend -> 仓库根(.env)
|
||
_MA_ROOT = _HERE.parents[3]
|
||
|
||
|
||
def _load_market_assistant_dotenv() -> None:
|
||
try:
|
||
from dotenv import load_dotenv
|
||
except ImportError:
|
||
return
|
||
p = _MA_ROOT / ".env"
|
||
if p.is_file():
|
||
load_dotenv(p)
|
||
|
||
|
||
def main() -> int:
|
||
_load_market_assistant_dotenv()
|
||
import requests
|
||
|
||
from .ingredients_defaults import (
|
||
IMAGE_REFERER,
|
||
MAX_TOKENS,
|
||
PROMPT_DEFAULT,
|
||
QWEN_OMNI_TEMPLATE,
|
||
TEMPERATURE,
|
||
USER_PROMPT,
|
||
)
|
||
from .ingredients_op import _ingredient_extraction_acceptable
|
||
from . import extract_ingredients_from_image
|
||
|
||
try:
|
||
if hasattr(sys.stdout, "reconfigure"):
|
||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||
if hasattr(sys.stderr, "reconfigure"):
|
||
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
||
except Exception:
|
||
pass
|
||
|
||
src = (IMAGE_SOURCE or "").strip()
|
||
if not src:
|
||
print(
|
||
"[openai_gateway] 请在本文件 __main__.py 顶部设置 IMAGE_SOURCE(图片路径或 URL)。",
|
||
file=sys.stderr,
|
||
)
|
||
return 2
|
||
|
||
prompt_use = (USER_PROMPT or "").strip() or None
|
||
extra: dict[str, Any] | None = None
|
||
if QWEN_OMNI_TEMPLATE:
|
||
extra = {"chat_template_kwargs": {"enable_thinking": False}}
|
||
|
||
try:
|
||
text = extract_ingredients_from_image(
|
||
src,
|
||
user_prompt=prompt_use,
|
||
referer=(IMAGE_REFERER or "https://www.jd.com/").strip(),
|
||
temperature=float(TEMPERATURE),
|
||
max_tokens=int(MAX_TOKENS),
|
||
extra_json=extra,
|
||
prompt_default=PROMPT_DEFAULT,
|
||
)
|
||
except ValueError as e:
|
||
print(f"[openai_gateway] {e}", file=sys.stderr)
|
||
return 2
|
||
except requests.HTTPError as e:
|
||
err_body = ""
|
||
if e.response is not None and e.response.text:
|
||
err_body = e.response.text[:1500]
|
||
print(f"[openai_gateway] HTTP 错误: {e}\n{err_body}", file=sys.stderr)
|
||
return 1
|
||
except Exception as e:
|
||
print(f"[openai_gateway] 失败: {e}", file=sys.stderr)
|
||
return 1
|
||
|
||
t = (text or "").strip()
|
||
if _ingredient_extraction_acceptable(t):
|
||
print(t)
|
||
return 0
|
||
print(
|
||
"【未通过配料表校验】输出须同时包含包装配料表常见结构(如「配料/配料表/原料/食品添加剂」)"
|
||
"与含量或百分比等信息,或为「××(含量≥x%)」形态;纯食材/菜谱备料枚举不会采纳。"
|
||
"与 extract_ingredients_from_body_image_urls_reversed 流水线规则一致。"
|
||
)
|
||
if t:
|
||
print(f"[openai_gateway] 模型原始输出(未采纳): {t}", file=sys.stderr)
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|