from __future__ import annotations from .shared_part_01 import * def _normalize_provider(raw: Optional[str]) -> str: provider = str(raw or "").strip().lower() provider = PROVIDER_ALIASES.get(provider, provider) if provider not in SUPPORTED_PROVIDERS: raise ValueError("provider 仅支持 deepseek/dashscope/openai/zhipu/ollama") return provider def _mask_secret(secret: str) -> str: value = str(secret or "").strip() if not value: return "" if len(value) <= 8: return "*" * len(value) return f"{value[:4]}...{value[-4:]}" PROVIDER_DISPLAY_LABELS = { "dashscope": "Qwen / DashScope", "openai": "OpenAI 兼容网关", "zhipu": "智谱 BigModel", "deepseek": "DeepSeek", "ollama": "本地 Ollama", } def _provider_display_label(raw: Any) -> str: provider = str(raw or "").strip().lower() provider = PROVIDER_ALIASES.get(provider, provider) return PROVIDER_DISPLAY_LABELS.get(provider, provider) def _dashscope_disable_thinking_for_strict_mode(*, provider: Any, model: Any) -> bool: normalized_provider = str(provider or "").strip().lower() normalized_model = str(model or "").strip().lower() if normalized_provider != "dashscope": return False return normalized_model.startswith(("qwen3.6", "qwen3.5", "qwen3-", "glm-5")) def _zhipu_disable_thinking_for_strict_mode(*, provider: Any, model: Any) -> bool: normalized_provider = str(provider or "").strip().lower() normalized_model = str(model or "").strip().lower() if normalized_provider != "zhipu": return False return normalized_model.startswith(("glm-5.1", "glm-5", "glm-4.7")) def _safe_json(value: Any) -> dict[str, Any]: if isinstance(value, dict): try: # 返回深拷贝,避免原地修改导致 SQLAlchemy 不感知 JSON 字段变更 return json.loads(json.dumps(value)) except Exception: return dict(value) if isinstance(value, str): try: parsed = json.loads(value) return parsed if isinstance(parsed, dict) else {} except Exception: return {} return {} CAPABILITY_SLOT_ALIASES = { "structured", "long_context", "tool", "external_query", "private", "multimodal", } def _optional_tier_alias(raw: Any) -> str: value = str(raw or "").strip().lower() return value if value in VALID_TIER_ALIASES or value in CAPABILITY_SLOT_ALIASES else "" def _optional_response_contract(raw: Any) -> str: value = str(raw or "").strip().lower() return value if value in {"structured", "freeform"} else "" def _optional_fallback_policy(raw: Any) -> str: value = str(raw or "").strip().lower() return value if value in {"fast_local", "default", "disabled"} else "" def _optional_execution_mode(raw: Any) -> str: value = str(raw or "").strip().lower() return value if value in {"remote", "local_planner", "local_worker"} else "" def _optional_meta_text(raw: Any) -> str: return str(raw or "").strip() def _optional_meta_int(raw: Any) -> int | None: if raw is None or raw == "": return None try: return int(raw) except (TypeError, ValueError): return None def _optional_meta_float(raw: Any) -> float | None: if raw is None or raw == "": return None try: return float(raw) except (TypeError, ValueError): return None def _normalize_routing_meta(raw: Any) -> dict[str, Any]: payload = _safe_json(raw) planned_tier = _optional_tier_alias(payload.get("planned_tier")) executed_tier = _optional_tier_alias(payload.get("executed_tier")) or planned_tier tier_alias = _optional_tier_alias(payload.get("tier_alias")) or planned_tier or executed_tier route_source = str(payload.get("route_source") or payload.get("source") or "").strip().lower() if route_source not in {"default", "override", "active_engine", "slot_binding", "provider_console", "probe_runner"}: route_source = "default" if tier_alias else "" rule_name = str(payload.get("route_rule_name") or payload.get("rule_name") or "").strip() decision = str(payload.get("routing_decision") or payload.get("decision") or "").strip() config_version = str(payload.get("routing_config_version") or "").strip() config_updated_at = str(payload.get("routing_config_updated_at") or "").strip() rule_priority_raw = payload.get("rule_priority") try: rule_priority = int(rule_priority_raw) if rule_priority_raw is not None else None except (TypeError, ValueError): rule_priority = None response_contract = _optional_response_contract(payload.get("response_contract")) fallback_policy = _optional_fallback_policy(payload.get("fallback_policy")) execution_mode = _optional_execution_mode(payload.get("execution_mode")) slot_key = _optional_tier_alias(payload.get("slot_key")) slot_version = str(payload.get("slot_version") or "").strip() slot_runtime_source = str(payload.get("slot_runtime_source") or "").strip().lower() if slot_runtime_source not in {"active_slot", "active_slot_degraded"}: slot_runtime_source = "" slot_fallback_index_raw = payload.get("slot_fallback_index") try: slot_fallback_index = int(slot_fallback_index_raw) if slot_fallback_index_raw is not None else None except (TypeError, ValueError): slot_fallback_index = None slot_degraded = bool(payload.get("slot_degraded", False)) provider_code = _optional_meta_text(payload.get("provider_code") or payload.get("provider")).lower() prompt_key = _optional_meta_text(payload.get("prompt_key")) prompt_source = _optional_meta_text(payload.get("prompt_source")) prompt_release_id = _optional_meta_int(payload.get("prompt_release_id")) prompt_format_error = bool(payload.get("prompt_format_error", False)) is_direct_operation = bool(payload.get("direct_operation", False)) normalized_decision = decision if not normalized_decision and (tier_alias or slot_key or planned_tier or executed_tier): normalized_decision = "primary_tier" return { "trace_id": _optional_meta_text(payload.get("trace_id")), "run_id": _optional_meta_text(payload.get("run_id")), "scene_key": _optional_meta_text(payload.get("scene_key")), "provider": provider_code, "provider_code": provider_code, "provider_label": _optional_meta_text(payload.get("provider_label")) or _provider_display_label(provider_code), "model": _optional_meta_text(payload.get("model")), "engine_id": _optional_meta_text(payload.get("engine_id")), "engine_name": _optional_meta_text(payload.get("engine_name")), "latency_ms": _optional_meta_int(payload.get("latency_ms")), "duration_ms": _optional_meta_int(payload.get("duration_ms")), "tier_alias": tier_alias, "planned_tier": planned_tier or tier_alias, "executed_tier": executed_tier or planned_tier or tier_alias, "route_source": route_source, "route_rule_name": rule_name, "routing_decision": normalized_decision, "routing_config_version": config_version, "routing_config_updated_at": config_updated_at, "rule_priority": rule_priority, "response_contract": response_contract, "fallback_policy": fallback_policy, "execution_mode": execution_mode, "slot_key": slot_key, "slot_version": slot_version, "slot_runtime_source": slot_runtime_source, "slot_fallback_index": slot_fallback_index, "slot_degraded": slot_degraded, "prompt_key": prompt_key, "prompt_release_id": prompt_release_id, "prompt_source": prompt_source, "prompt_format_error": prompt_format_error, "direct_operation": is_direct_operation, "probe_run_id": _optional_meta_text(payload.get("probe_run_id")), "probe_mode": _optional_meta_text(payload.get("probe_mode")), "probe_target": _optional_meta_text(payload.get("probe_target")), "probe_targets": payload.get("probe_targets") if isinstance(payload.get("probe_targets"), list) else [], "probe_method": _optional_meta_text(payload.get("probe_method")), "probe_status": _optional_meta_text(payload.get("probe_status")), "probe_summary": payload.get("probe_summary") if isinstance(payload.get("probe_summary"), dict) else {}, "evidence_strength": _optional_meta_text(payload.get("evidence_strength")), "failure_code": _optional_meta_text(payload.get("failure_code")), "upstream_request_sent": payload.get("upstream_request_sent") if isinstance(payload.get("upstream_request_sent"), bool) else None, "upstream_missing_reason": _optional_meta_text(payload.get("upstream_missing_reason")), "scene_timeout_policy_id": _optional_meta_text(payload.get("scene_timeout_policy_id")), "scene_timeout_policy_version": _optional_meta_text(payload.get("scene_timeout_policy_version")), "input_bucket": _optional_meta_text(payload.get("input_bucket")), "input_tokens_estimate": _optional_meta_int(payload.get("input_tokens_estimate")), "foreground_wait_seconds": _optional_meta_float(payload.get("foreground_wait_seconds")), "provider_timeout_seconds": _optional_meta_float(payload.get("provider_timeout_seconds")), "job_timeout_seconds": _optional_meta_float(payload.get("job_timeout_seconds")), "max_retries": _optional_meta_int(payload.get("max_retries")), "allow_low_to_high_escalation": ( payload.get("allow_low_to_high_escalation") if isinstance(payload.get("allow_low_to_high_escalation"), bool) else None ), "disable_thinking": ( payload.get("disable_thinking") if isinstance(payload.get("disable_thinking"), bool) else None ), "function_runtime_profile_version": _optional_meta_text(payload.get("function_runtime_profile_version")), "function_runtime_profile_source": _optional_meta_text(payload.get("function_runtime_profile_source")), "function_runtime_max_tokens": _optional_meta_int(payload.get("function_runtime_max_tokens")), "function_runtime_repair_max_tokens": _optional_meta_int(payload.get("function_runtime_repair_max_tokens")), "provider_usage": payload.get("provider_usage") if isinstance(payload.get("provider_usage"), dict) else {}, "scene_fallback_policy": _optional_meta_text(payload.get("scene_fallback_policy")), "large_input_policy": _optional_meta_text(payload.get("large_input_policy")), "timeout_policy_source": _optional_meta_text(payload.get("timeout_policy_source")), "timeout_policy_reason": _optional_meta_text(payload.get("timeout_policy_reason")), } def _read_engine_routing_meta(engine: Any) -> dict[str, Any]: payload = engine.get("_routing_meta") if isinstance(engine, dict) else {} return _normalize_routing_meta(payload) def _merge_call_routing_meta(*, caller_meta: Any, engine_meta: Any) -> dict[str, Any]: caller = _normalize_routing_meta(caller_meta) engine = _normalize_routing_meta(engine_meta) merged = dict(caller) for key, value in engine.items(): if value is None or value == "": continue merged[key] = value if engine.get("slot_degraded"): merged["slot_degraded"] = True if engine.get("prompt_format_error"): merged["prompt_format_error"] = True return _normalize_routing_meta(merged) def _merge_engine_routing_meta(engine: dict[str, Any], **updates: Any) -> dict[str, Any]: runtime = dict(engine or {}) current = _read_engine_routing_meta(runtime) for key, value in updates.items(): if value is None: continue current[key] = value runtime["_routing_meta"] = _normalize_routing_meta(current) return runtime def _routing_meta_log_text(meta: Any) -> str: data = _normalize_routing_meta(meta) parts = [] if data.get("planned_tier"): parts.append(f"planned_tier={data['planned_tier']}") if data.get("executed_tier"): parts.append(f"executed_tier={data['executed_tier']}") if data.get("route_source"): parts.append(f"source={data['route_source']}") if data.get("route_rule_name"): parts.append(f"rule={data['route_rule_name']}") if data.get("routing_decision"): parts.append(f"decision={data['routing_decision']}") if data.get("slot_key"): parts.append(f"slot_key={data['slot_key']}") if data.get("slot_version"): parts.append(f"slot_version={data['slot_version']}") if data.get("slot_runtime_source"): parts.append(f"slot_runtime_source={data['slot_runtime_source']}") if data.get("slot_fallback_index") is not None: parts.append(f"slot_fallback_index={data['slot_fallback_index']}") if data.get("slot_degraded"): parts.append("slot_degraded=true") return ", ".join(parts) def _env_bool(name: str, default: bool = False) -> bool: raw = os.getenv(name) if raw is None: return default return str(raw).strip().lower() in BOOL_TRUE_VALUES def _parse_csv_items(raw: str) -> tuple[str, ...]: rows = [item.strip().lower() for item in str(raw or "").split(",") if item.strip()] return tuple(rows) def _cn_now_text() -> str: cn_tz = timezone(timedelta(hours=8)) return datetime.now(cn_tz).strftime("%Y-%m-%d %H:%M:%S") def _cn_now_text_ms() -> str: cn_tz = timezone(timedelta(hours=8)) return datetime.now(cn_tz).strftime("%Y-%m-%d %H:%M:%S.%f")[:-3] def _runtime_log(scope: str, message: str) -> None: print(f"[{_cn_now_text()}][{scope}] {message}") def _is_control_plane_timeout_message(text: str) -> bool: lowered = str(text or "").strip().lower() if not lowered: return False timeout_signals = ( "request timed out before a response was generated", "agents.defaults.timeoutseconds", "timeoutseconds", "before a response was generated", ) return any(signal in lowered for signal in timeout_signals) @dataclass class ChatCompletionResult: text: str raw_request: Any = None raw_response: Any = None provider_attempts: Optional[list[dict[str, Any]]] = None @dataclass class StructuredExtractionResult: payload: Optional[dict[str, Any]] source_field: str provider: str model: str error_code: Optional[str] = None raw_text: str = "" validation: str = "invalid" from_cache: bool = False __all__ = [name for name in globals() if not name.startswith("__")]