(self, payload: Dict[str, Any], label: str)
| 50 | return response.content |
| 51 | |
| 52 | def _post_json(self, payload: Dict[str, Any], label: str) -> Dict[str, Any]: |
| 53 | url = f"{self.policy.base_url}{self.policy.endpoint_type}" |
| 54 | request_payload = dict(payload) |
| 55 | if self.policy.response_format and "response_format" not in request_payload: |
| 56 | request_payload["response_format"] = self.policy.response_format |
| 57 | |
| 58 | downgraded_response_format = False |
| 59 | transient_attempt = 0 |
| 60 | |
| 61 | while True: |
| 62 | try: |
| 63 | logger.debug(f"{label} 请求: {url}") |
| 64 | response = self.session.post( |
| 65 | url, |
| 66 | headers=self._headers(), |
| 67 | json=request_payload, |
| 68 | timeout=self.timeout, |
| 69 | ) |
| 70 | except ( |
| 71 | requests.exceptions.SSLError, |
| 72 | requests.exceptions.ConnectionError, |
| 73 | requests.exceptions.Timeout, |
| 74 | ) as exc: |
| 75 | if transient_attempt >= 2: |
| 76 | raise Exception(f"{label} 连接失败: {str(exc)}") from exc |
| 77 | self._sleep_for_retry(transient_attempt) |
| 78 | transient_attempt += 1 |
| 79 | continue |
| 80 | |
| 81 | if response.status_code == 200: |
| 82 | return response.json() |
| 83 | |
| 84 | error_detail = response.text[:500] |
| 85 | if ( |
| 86 | "response_format" in request_payload |
| 87 | and not downgraded_response_format |
| 88 | and _is_unknown_response_format(error_detail) |
| 89 | ): |
| 90 | logger.warning("上游不支持 response_format,移除后重试一次") |
| 91 | request_payload.pop("response_format", None) |
| 92 | downgraded_response_format = True |
| 93 | continue |
| 94 | |
| 95 | if response.status_code == 429 or response.status_code >= 500: |
| 96 | if transient_attempt < 2: |
| 97 | self._sleep_for_retry(transient_attempt, response) |
| 98 | transient_attempt += 1 |
| 99 | continue |
| 100 | |
| 101 | logger.error(f"{label} 请求失败: status={response.status_code}, error={error_detail}") |
| 102 | raise Exception( |
| 103 | f"{label} 请求失败 (状态码: {response.status_code})\n" |
| 104 | f"错误详情: {error_detail}\n" |
| 105 | f"请求地址: {url}" |
| 106 | ) |
| 107 | |
| 108 | def _headers(self) -> Dict[str, str]: |
| 109 | return { |
no test coverage detected