Spaces:
Running
Running
File size: 3,417 Bytes
79df050 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timezone
from typing import Any, Dict, Optional
@dataclass(frozen=True)
class EnvironmentInjection:
summary_text: str
raw_context: Dict[str, Any]
metadata: Dict[str, Any]
class EnvironmentContextBuilder:
"""
將最新環境快照轉成固定可注入格式。
設計目標:
1. 每回合固定注入,但內容結構固定,避免 prompt 漂移
2. 同時保留 raw context,供工具與 runtime 做更細緻決策
3. 缺資料時明確標記 freshness / completeness,而不是靜默忽略
"""
def build(
self,
env_context: Optional[Dict[str, Any]],
*,
now: Optional[datetime] = None,
) -> EnvironmentInjection:
ctx = dict(env_context or {})
current_time = now or datetime.now(timezone.utc)
lines = [
f"snapshot_time_utc: {current_time.isoformat()}",
f"has_location: {self._has_location(ctx)}",
f"has_address: {bool(ctx.get('detailed_address') or ctx.get('address_display') or ctx.get('label'))}",
f"has_timezone: {bool(ctx.get('tz'))}",
f"has_locale: {bool(ctx.get('locale'))}",
]
if ctx.get("detailed_address"):
lines.append(f"detailed_address: {ctx['detailed_address']}")
elif ctx.get("address_display"):
lines.append(f"address_display: {ctx['address_display']}")
elif ctx.get("label"):
lines.append(f"label: {ctx['label']}")
if ctx.get("city"):
lines.append(f"city: {ctx['city']}")
if ctx.get("admin"):
lines.append(f"admin: {ctx['admin']}")
if ctx.get("country_code"):
lines.append(f"country_code: {ctx['country_code']}")
if ctx.get("precision"):
lines.append(f"precision: {ctx['precision']}")
if ctx.get("poi_label"):
lines.append(f"poi_label: {ctx['poi_label']}")
if ctx.get("road"):
lines.append(f"road: {ctx['road']}")
if ctx.get("house_number"):
lines.append(f"house_number: {ctx['house_number']}")
if ctx.get("tz"):
lines.append(f"timezone: {ctx['tz']}")
if ctx.get("locale"):
lines.append(f"locale: {ctx['locale']}")
if ctx.get("heading_cardinal"):
lines.append(f"heading: {ctx['heading_cardinal']}")
elif ctx.get("heading_deg") is not None:
lines.append(f"heading_deg: {ctx['heading_deg']}")
if ctx.get("accuracy_m") is not None:
lines.append(f"accuracy_m: {ctx['accuracy_m']}")
if ctx.get("lat") is not None and ctx.get("lon") is not None:
lines.append(f"coordinates: {ctx['lat']},{ctx['lon']}")
metadata = {
"source": "environment_context_service",
"freshness": "latest_available" if ctx else "missing",
"has_location": self._has_location(ctx),
"has_timezone": bool(ctx.get("tz")),
"has_locale": bool(ctx.get("locale")),
}
return EnvironmentInjection(
summary_text="\n".join(lines),
raw_context=ctx,
metadata=metadata,
)
@staticmethod
def _has_location(ctx: Dict[str, Any]) -> bool:
return ctx.get("lat") is not None and ctx.get("lon") is not None
|