v1.6: Platform Gateway — Amazon/JD/Taobao/PDD/TikTok 5平台API集成 + start_provision_v2.sh
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Unified result object returned by all channel adapters."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class UnifiedResult:
|
||||
"""A platform-agnostic representation of a fetch outcome.
|
||||
|
||||
``status`` semantics:
|
||||
success - data fetched, ``data`` is populated
|
||||
cache_hit - served from local LRU cache
|
||||
rate_limited - tenant or platform quota exhausted
|
||||
breaker_open - circuit breaker tripped
|
||||
error - platform errored, ``error`` populated
|
||||
timeout - exceeded per-call timeout
|
||||
no_creds - tenant has not authorised this channel
|
||||
"""
|
||||
|
||||
status: str
|
||||
data: dict | list | None = None
|
||||
error: str | None = None
|
||||
latency_ms: int = 0
|
||||
channel: str = ""
|
||||
raw: dict | None = field(default=None, repr=False)
|
||||
|
||||
@property
|
||||
def ok(self) -> bool:
|
||||
return self.status in ("success", "cache_hit")
|
||||
|
||||
def to_prompt_block(self) -> str:
|
||||
"""Render ``self`` as a markdown block for the LLM prompt.
|
||||
|
||||
Returns a short failure hint on platform errors so the LLM does not
|
||||
hallucinate prices/stock. Returns empty on ``no_creds`` (silent skip).
|
||||
"""
|
||||
if self.status == "no_creds":
|
||||
return ""
|
||||
if not self.ok or not self.data:
|
||||
if self.status == "rate_limited":
|
||||
return "📦 实时商品数据: 触发限流,请稍后重试"
|
||||
if self.status == "breaker_open":
|
||||
return "📦 实时商品数据: 平台服务暂时不可用(熔断)"
|
||||
if self.status == "timeout":
|
||||
return "📦 实时商品数据: 请求超时,已跳过"
|
||||
return "📦 实时商品数据: 平台 API 暂不可用,请基于现有知识谨慎回答(不要编造价格/库存)"
|
||||
lines = ["📦 实时商品信息:"]
|
||||
# data shape (per channel): {"title": ..., "price": ..., "currency": ..., "url": ..., "in_stock": ...}
|
||||
d = self.data
|
||||
if isinstance(d, dict):
|
||||
if d.get("title"):
|
||||
lines.append(f" - 商品: {d['title']}")
|
||||
if d.get("price") is not None:
|
||||
cur = d.get("currency", "")
|
||||
lines.append(f" - 价格: {cur} {d['price']}".strip())
|
||||
if d.get("in_stock") is not None:
|
||||
lines.append(f" - 库存: {'有' if d['in_stock'] else '无'}")
|
||||
if d.get("url"):
|
||||
lines.append(f" - 链接: {d['url']}")
|
||||
elif isinstance(d, list):
|
||||
for i, item in enumerate(d[:3], 1):
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
title = item.get("title", "(无标题)")
|
||||
price = item.get("price")
|
||||
cur = item.get("currency", "")
|
||||
lines.append(f" {i}. {title} — {cur} {price}".strip())
|
||||
return "\n".join(lines)
|
||||
Reference in New Issue
Block a user