107 lines
3.1 KiB
Python
107 lines
3.1 KiB
Python
"""
|
|
千问:整理 Excel/PDF 抽出的原文。
|
|
|
|
本文件职责:把抽文本结果交给 qwen-plus,只整理看得见的字,不填询价字段。
|
|
属于 llm 包。单测注入 chat_fn。禁止算最终缺项、禁止发明港口/箱型。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Any, Optional
|
|
|
|
from agent.llm.modes import LlmMode
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
MODE = LlmMode.ATTACHMENT_TEXT
|
|
|
|
ATTACH_SYSTEM = (
|
|
"下面是从 Excel 或 PDF 抽出来的原文。请整理成一段可读的询价口播:"
|
|
"只保留材料里已经出现的文字和数字,原样保留港口、机场三字码、箱型、重量。"
|
|
"看不清或没出现的不要猜,不要补询价缺项,不要发明港口、重量或日期。"
|
|
"材料完全没有询价信息时输出空。"
|
|
)
|
|
|
|
|
|
def mode_meta() -> dict[str, Any]:
|
|
return {
|
|
"mode": MODE.value,
|
|
"provider": "qwen",
|
|
"purpose": "attachment_text",
|
|
"implemented": True,
|
|
}
|
|
|
|
|
|
def _pack_text(text: str, *, stub: bool = False) -> dict[str, Any]:
|
|
body = (text or "").strip()
|
|
return {
|
|
"ok": True,
|
|
"stub": stub,
|
|
"mode": MODE.value,
|
|
"text": body,
|
|
"empty": not bool(body),
|
|
"error": "",
|
|
}
|
|
|
|
|
|
def invoke_shell(*, payload: dict[str, Any]) -> dict[str, Any]:
|
|
"""
|
|
无网/单测入口:优先 assistant_text;否则把 raw_text 当整理结果。
|
|
"""
|
|
data = dict(payload or {})
|
|
if "assistant_text" in data:
|
|
return _pack_text(str(data.get("assistant_text") or ""), stub=True)
|
|
if "raw_text" in data:
|
|
return _pack_text(str(data.get("raw_text") or ""), stub=True)
|
|
return {
|
|
"ok": False,
|
|
"stub": True,
|
|
"mode": MODE.value,
|
|
"text": "",
|
|
"empty": True,
|
|
"error": "attachment_text_shell_not_implemented",
|
|
"echo_keys": sorted(data.keys()),
|
|
}
|
|
|
|
|
|
def invoke_attachment_text(
|
|
*,
|
|
payload: dict[str, Any],
|
|
chat_fn: Optional[Any] = None,
|
|
allow_network: bool = False,
|
|
) -> dict[str, Any]:
|
|
"""
|
|
整理一份抽出原文。chat_fn 单测注入;无网走 invoke_shell。
|
|
"""
|
|
data = dict(payload or {})
|
|
raw = str(data.get("raw_text") or "")
|
|
if chat_fn is None and not allow_network:
|
|
return invoke_shell(payload=data)
|
|
if not raw.strip():
|
|
return _pack_text("", stub=chat_fn is None)
|
|
if chat_fn is None:
|
|
from agent.llm.http_client import LlmHttpClient
|
|
|
|
client = LlmHttpClient.from_settings()
|
|
chat_fn = client.chat
|
|
messages = [
|
|
{"role": "system", "content": ATTACH_SYSTEM},
|
|
{"role": "user", "content": raw.strip()},
|
|
]
|
|
result = chat_fn(mode=MODE, messages=messages)
|
|
if not getattr(result, "ok", False):
|
|
err = str(getattr(result, "error", "") or "attachment_text_failed")
|
|
logger.info("attachment_text 失败 err=%s", err)
|
|
return {
|
|
"ok": False,
|
|
"stub": False,
|
|
"mode": MODE.value,
|
|
"text": "",
|
|
"empty": True,
|
|
"error": err,
|
|
}
|
|
packed = _pack_text(str(getattr(result, "content", "") or ""))
|
|
packed["stub"] = False
|
|
return packed
|