Update openai_ondemand_adapter.py
Browse files- openai_ondemand_adapter.py +35 -70
openai_ondemand_adapter.py
CHANGED
|
@@ -255,35 +255,32 @@ def _execute_one_stream_attempt(apikey_for_attempt, session_id_for_attempt, quer
|
|
| 255 |
accumulated_text_parts = []
|
| 256 |
api_error_yielded = False
|
| 257 |
|
| 258 |
-
# Inner retry loop for 500 errors specifically for this attempt
|
| 259 |
max_500_retries_for_this_call = 5
|
| 260 |
current_500_retry_count = 0
|
| 261 |
|
| 262 |
while current_500_retry_count < max_500_retries_for_this_call:
|
| 263 |
current_500_retry_count += 1
|
| 264 |
-
if current_500_retry_count > 1:
|
| 265 |
logging.info(f"【流式请求子尝试 {current_attempt_num_logging} - 500错误重试 {current_500_retry_count-1}/{max_500_retries_for_this_call-1}】Key: {keymgr.display_key(apikey_for_attempt)}")
|
| 266 |
else:
|
| 267 |
logging.info(f"【流式请求子尝试 {current_attempt_num_logging}】发送到 OnDemand: Session={session_id_for_attempt}, Endpoint={endpoint_id}, Key={keymgr.display_key(apikey_for_attempt)}")
|
| 268 |
|
| 269 |
-
|
| 270 |
try:
|
| 271 |
with requests.post(url, json=payload, headers=headers, stream=True, timeout=180) as resp:
|
| 272 |
-
if resp.status_code == 500:
|
| 273 |
logging.warning(f"【OnDemand流错误】(子尝试 {current_attempt_num_logging}, 500重试 {current_500_retry_count}) 收到500错误。Session: {session_id_for_attempt}")
|
| 274 |
if current_500_retry_count >= max_500_retries_for_this_call:
|
| 275 |
logging.error(f"【OnDemand流错误】(子尝试 {current_attempt_num_logging}) 达到500错误最大重试次数。将错误传递给上层。")
|
| 276 |
-
# Yield a specific error for persistent 500 after retries
|
| 277 |
api_error_yielded = True
|
| 278 |
error_payload = {"error": {"message": f"OnDemand API persistent 500 error after {max_500_retries_for_this_call} retries (Attempt {current_attempt_num_logging}).",
|
| 279 |
"type": "on_demand_persistent_500_error", "code": 500}}
|
| 280 |
yield format_openai_sse_delta(error_payload)
|
| 281 |
yield "data: [DONE]\n\n"
|
| 282 |
return "".join(accumulated_text_parts).strip(), api_error_yielded
|
| 283 |
-
time.sleep(1)
|
| 284 |
-
continue
|
| 285 |
|
| 286 |
-
if resp.status_code != 200:
|
| 287 |
api_error_yielded = True
|
| 288 |
error_text = resp.text
|
| 289 |
logging.error(f"【OnDemand流错误】请求失败 (子尝试 {current_attempt_num_logging})。状态码: {resp.status_code}, Session: {session_id_for_attempt}, 响应: {error_text[:500]}")
|
|
@@ -298,7 +295,6 @@ def _execute_one_stream_attempt(apikey_for_attempt, session_id_for_attempt, quer
|
|
| 298 |
yield "data: [DONE]\n\n"
|
| 299 |
return "".join(accumulated_text_parts).strip(), api_error_yielded
|
| 300 |
|
| 301 |
-
# Successful 200 response, process stream
|
| 302 |
first_chunk_sent = False
|
| 303 |
last_line_str = ""
|
| 304 |
for line_bytes in resp.iter_lines():
|
|
@@ -356,17 +352,13 @@ def _execute_one_stream_attempt(apikey_for_attempt, session_id_for_attempt, quer
|
|
| 356 |
if not api_error_yielded and not last_line_str.startswith("data: [DONE]"):
|
| 357 |
logging.info(f"【OnDemand流】(子尝试 {current_attempt_num_logging}) 流迭代完成,补充发送 [DONE]。Session: {session_id_for_attempt}")
|
| 358 |
yield "data: [DONE]\n\n"
|
| 359 |
-
return "".join(accumulated_text_parts).strip(), api_error_yielded
|
| 360 |
|
| 361 |
except requests.exceptions.RequestException as e_req_inner:
|
| 362 |
-
# This catches network errors or HTTP errors if resp.raise_for_status() was called (e.g. for persistent 500)
|
| 363 |
logging.error(f"【OnDemand流】(子尝试 {current_attempt_num_logging}) 请求时发生异常: {e_req_inner}, Key: {keymgr.display_key(apikey_for_attempt)}")
|
| 364 |
-
# If this was the last 500-retry, or another RequestException, re-raise to be handled by handle_stream_request's try-except
|
| 365 |
if current_500_retry_count >= max_500_retries_for_this_call or (hasattr(e_req_inner, 'response') and e_req_inner.response is not None and e_req_inner.response.status_code != 500):
|
| 366 |
raise e_req_inner
|
| 367 |
-
|
| 368 |
-
time.sleep(1) # Wait before retrying the 500 error
|
| 369 |
-
# The loop will continue to the next 500-retry.
|
| 370 |
|
| 371 |
except Exception as e_inner_unknown:
|
| 372 |
logging.error(f"【OnDemand流】处理流时发生未知��误 (子尝试 {current_attempt_num_logging}): {e_inner_unknown}, Session: {session_id_for_attempt}", exc_info=True)
|
|
@@ -378,10 +370,7 @@ def _execute_one_stream_attempt(apikey_for_attempt, session_id_for_attempt, quer
|
|
| 378 |
yield "data: [DONE]\n\n"
|
| 379 |
return "".join(accumulated_text_parts).strip(), api_error_yielded
|
| 380 |
|
| 381 |
-
# If 500-retry loop exhausted without returning (should ideally raise inside or return success)
|
| 382 |
logging.error(f"【OnDemand流】(子尝试 {current_attempt_num_logging}) 500错误重试循环意外结束。")
|
| 383 |
-
# This case should ideally not be reached if logic inside loop is correct.
|
| 384 |
-
# Re-raise a generic error to be caught by the caller if it does.
|
| 385 |
raise requests.exceptions.RequestException(f"Exhausted internal 500 retries for attempt {current_attempt_num_logging} without success or specific error propagation.")
|
| 386 |
|
| 387 |
|
|
@@ -517,7 +506,7 @@ def handle_stream_request(initial_apikey, initial_session_id, query_str, endpoin
|
|
| 517 |
while empty_retry_attempt_num < max_empty_response_retries:
|
| 518 |
empty_retry_attempt_num += 1
|
| 519 |
accumulated_text_this_attempt = ""
|
| 520 |
-
api_error_in_attempt = False
|
| 521 |
|
| 522 |
if empty_retry_attempt_num > 1:
|
| 523 |
logging.info(f"【流式请求-空回复重试 {empty_retry_attempt_num-1}】获取新Key/Session...")
|
|
@@ -553,7 +542,6 @@ def handle_stream_request(initial_apikey, initial_session_id, query_str, endpoin
|
|
| 553 |
log_attempt_str = f"初始尝试" if empty_retry_attempt_num == 1 else f"空回复重试 {empty_retry_attempt_num-1}"
|
| 554 |
|
| 555 |
try:
|
| 556 |
-
# result_tuple will be (accumulated_text, api_error_yielded_flag_from_execute)
|
| 557 |
result_tuple = yield from _execute_one_stream_attempt(
|
| 558 |
current_apikey_for_attempt,
|
| 559 |
current_session_id_for_attempt,
|
|
@@ -563,9 +551,9 @@ def handle_stream_request(initial_apikey, initial_session_id, query_str, endpoin
|
|
| 563 |
f"{log_attempt_str} (Overall attempt {empty_retry_attempt_num})"
|
| 564 |
)
|
| 565 |
accumulated_text_this_attempt = result_tuple[0]
|
| 566 |
-
api_error_in_attempt = result_tuple[1]
|
| 567 |
|
| 568 |
-
except requests.exceptions.RequestException as e_req:
|
| 569 |
log_key_display = keymgr.display_key(current_apikey_for_attempt) if current_apikey_for_attempt else "N/A"
|
| 570 |
status_code_from_exc_stream = None
|
| 571 |
if hasattr(e_req, 'response') and e_req.response is not None:
|
|
@@ -582,11 +570,8 @@ def handle_stream_request(initial_apikey, initial_session_id, query_str, endpoin
|
|
| 582 |
keymgr.mark_bad(current_apikey_for_attempt)
|
| 583 |
|
| 584 |
if empty_retry_attempt_num == 1:
|
| 585 |
-
# If the very first attempt (initial_apikey) fails with RequestException,
|
| 586 |
-
# re-raise to let with_valid_key_and_session handle key rotation.
|
| 587 |
raise e_req
|
| 588 |
|
| 589 |
-
# If it's an empty-response retry (attempt_num > 1) that failed with RequestException
|
| 590 |
if empty_retry_attempt_num >= max_empty_response_retries:
|
| 591 |
final_error_message = "重试次数过多,请检查上下文长度! 或联系管理员!"
|
| 592 |
final_error_code = "max_retries_check_context_contact_admin"
|
|
@@ -595,20 +580,16 @@ def handle_stream_request(initial_apikey, initial_session_id, query_str, endpoin
|
|
| 595 |
yield "data: [DONE]\n\n"
|
| 596 |
return
|
| 597 |
time.sleep(1)
|
| 598 |
-
continue
|
| 599 |
|
| 600 |
-
# After _execute_one_stream_attempt has finished (either normally or yielded its own error)
|
| 601 |
if api_error_in_attempt:
|
| 602 |
-
# This means _execute_one_stream_attempt handled an API error (like 429, or persistent 500) and yielded an error SSE.
|
| 603 |
-
# The stream is already complete with an error.
|
| 604 |
logging.warning(f"【流式请求】({log_attempt_str}) 子尝试已处理并流式传输API错误。")
|
| 605 |
-
return
|
| 606 |
|
| 607 |
if accumulated_text_this_attempt:
|
| 608 |
logging.info(f"【流式请求】({log_attempt_str}) 成功获取非空内容。")
|
| 609 |
-
return
|
| 610 |
|
| 611 |
-
# If we reach here, content was empty from _execute_one_stream_attempt, and no API error was yielded by it.
|
| 612 |
logging.warning(f"【流式请求】({log_attempt_str}) 返回空内容。")
|
| 613 |
if empty_retry_attempt_num >= max_empty_response_retries:
|
| 614 |
final_error_message = "重试次数过多,请检查上下文长度! 或联系管理员!"
|
|
@@ -637,6 +618,8 @@ def handle_non_stream_request(initial_apikey, initial_session_id, query_str, end
|
|
| 637 |
current_apikey_for_attempt = initial_apikey
|
| 638 |
current_session_id_for_attempt = initial_session_id
|
| 639 |
|
|
|
|
|
|
|
| 640 |
while empty_retry_attempt_num < max_empty_response_retries:
|
| 641 |
empty_retry_attempt_num += 1
|
| 642 |
|
|
@@ -671,10 +654,12 @@ def handle_non_stream_request(initial_apikey, initial_session_id, query_str, end
|
|
| 671 |
|
| 672 |
log_attempt_str = f"初始尝试" if empty_retry_attempt_num == 1 else f"空回复重试 {empty_retry_attempt_num-1}"
|
| 673 |
|
| 674 |
-
# Inner loop for 500-error retries for the current key/session
|
| 675 |
max_500_retries_for_this_call = 5
|
| 676 |
current_500_retry_count = 0
|
| 677 |
|
|
|
|
|
|
|
|
|
|
| 678 |
while current_500_retry_count < max_500_retries_for_this_call:
|
| 679 |
current_500_retry_count += 1
|
| 680 |
if current_500_retry_count > 1:
|
|
@@ -682,8 +667,9 @@ def handle_non_stream_request(initial_apikey, initial_session_id, query_str, end
|
|
| 682 |
else:
|
| 683 |
logging.info(f"【同步请求】({log_attempt_str}, 总尝试 {empty_retry_attempt_num}) Session={current_session_id_for_attempt}, Key={keymgr.display_key(current_apikey_for_attempt)}")
|
| 684 |
|
| 685 |
-
url = f"{ONDEMAND_API_BASE}/sessions/{current_session_id_for_attempt}/query"
|
| 686 |
-
|
|
|
|
| 687 |
headers = {"apikey": current_apikey_for_attempt, "Content-Type": "application/json"}
|
| 688 |
|
| 689 |
try:
|
|
@@ -693,13 +679,12 @@ def handle_non_stream_request(initial_apikey, initial_session_id, query_str, end
|
|
| 693 |
logging.warning(f"【OnDemand同步错误】({log_attempt_str}, 500重试 {current_500_retry_count}) 收到500错误。")
|
| 694 |
if current_500_retry_count >= max_500_retries_for_this_call:
|
| 695 |
logging.error(f"【OnDemand同步错误】({log_attempt_str}) 达到500错误最大重试次数。将错误传递给上层。")
|
| 696 |
-
resp.raise_for_status()
|
| 697 |
time.sleep(1)
|
| 698 |
-
continue
|
| 699 |
|
| 700 |
-
resp.raise_for_status()
|
| 701 |
|
| 702 |
-
# Successful 200 OK
|
| 703 |
response_json = resp.json()
|
| 704 |
if "data" not in response_json or "answer" not in response_json["data"]:
|
| 705 |
logging.error(f"【OnDemand同步错误】响应格式不符合预期 ({log_attempt_str})。Session: {current_session_id_for_attempt}, 响应: {str(response_json)[:500]}")
|
|
@@ -718,13 +703,10 @@ def handle_non_stream_request(initial_apikey, initial_session_id, query_str, end
|
|
| 718 |
}
|
| 719 |
return jsonify(openai_response_obj) # SUCCESS
|
| 720 |
else:
|
| 721 |
-
# Empty response after a 200 OK (and non-500 error)
|
| 722 |
logging.warning(f"【同步请求】({log_attempt_str}, 500重试 {current_500_retry_count}) 返回空回复。")
|
| 723 |
-
|
| 724 |
-
# Break from the 500-retry loop to let the outer empty-response loop handle it.
|
| 725 |
-
break # Break from current_500_retry_count loop
|
| 726 |
|
| 727 |
-
except requests.exceptions.RequestException as e_req:
|
| 728 |
log_key_display_sync = keymgr.display_key(current_apikey_for_attempt) if current_apikey_for_attempt else "N/A"
|
| 729 |
status_code_from_exc_sync = None
|
| 730 |
if hasattr(e_req, 'response') and e_req.response is not None:
|
|
@@ -732,38 +714,25 @@ def handle_non_stream_request(initial_apikey, initial_session_id, query_str, end
|
|
| 732 |
|
| 733 |
logging.warning(f"【同步请求】({log_attempt_str}, 500重试 {current_500_retry_count} using key {log_key_display_sync}) 发生请求级错误: {e_req}, Status: {status_code_from_exc_sync}")
|
| 734 |
|
| 735 |
-
# Key marking is handled by with_valid_key_and_session based on what's re-raised.
|
| 736 |
-
# If it's a 500 that exhausted its inner retries, it will be re-raised.
|
| 737 |
-
# If it's another RequestException, it's also re-raised.
|
| 738 |
-
|
| 739 |
-
# If this was the initial overall attempt (empty_retry_attempt_num == 1)
|
| 740 |
-
# AND this specific 500-retry loop has exhausted OR it's not a 500 error that can be retried by this inner loop:
|
| 741 |
if current_500_retry_count >= max_500_retries_for_this_call or status_code_from_exc_sync != 500:
|
| 742 |
if empty_retry_attempt_num == 1:
|
| 743 |
-
raise e_req
|
| 744 |
else:
|
| 745 |
-
|
| 746 |
-
# This attempt for this key has failed. Break 500-retry loop to go to next empty-response attempt.
|
| 747 |
-
# To signal this failure for the current key/session to the outer empty-response loop:
|
| 748 |
-
raise e_req # This will be caught by the outer try-except in the empty_retry_attempt_num loop
|
| 749 |
|
| 750 |
-
# If it was a 500 and we still have 500-retries, the loop will continue after sleep.
|
| 751 |
time.sleep(1)
|
| 752 |
-
|
| 753 |
|
| 754 |
except (ValueError, KeyError, json.JSONDecodeError) as e_parse:
|
| 755 |
logging.error(f"【同步请求】({log_attempt_str}, 500重试 {current_500_retry_count}) 处理响应或格式时出错: {e_parse}", exc_info=True)
|
| 756 |
-
if empty_retry_attempt_num == 1 and current_500_retry_count == 1 :
|
| 757 |
raise requests.exceptions.RequestException(f"Response format error on first attempt: {e_parse}") from e_parse
|
| 758 |
-
# If format error during a retry, it's a failure for this key/session attempt
|
| 759 |
-
# Break from 500-retry loop, let empty-response loop handle it.
|
| 760 |
-
# To signal this failure for the current key/session:
|
| 761 |
raise requests.exceptions.RequestException(f"Response format error during retry: {e_parse}") from e_parse
|
| 762 |
|
| 763 |
-
|
| 764 |
-
|
| 765 |
-
|
| 766 |
-
|
| 767 |
if empty_retry_attempt_num >= max_empty_response_retries:
|
| 768 |
final_error_message = "重试次数过多,请检查上下文长度! 或联系管理员!"
|
| 769 |
final_error_code = "max_retries_check_context_contact_admin"
|
|
@@ -777,12 +746,8 @@ def handle_non_stream_request(initial_apikey, initial_session_id, query_str, end
|
|
| 777 |
}), 500
|
| 778 |
logging.info(f"【同步请求】空回复(在500-重试循环之后),准备进行下一个空回复尝试。当前总尝试 {empty_retry_attempt_num}/{max_empty_response_retries}")
|
| 779 |
time.sleep(1)
|
| 780 |
-
# Outer loop (empty_retry_attempt_num) will continue
|
| 781 |
-
# If we are here and didn't return a success, it means the 500-retry loop might have been exhausted by 500s
|
| 782 |
-
# but didn't re-raise correctly, or some other path. This is a fallback.
|
| 783 |
-
# However, if it exhausted 500s, it should have re-raised an exception.
|
| 784 |
|
| 785 |
-
# Fallback if outer empty_retry_attempt_num loop finishes
|
| 786 |
final_fallback_error_message = "重试次数过多,请检查上下文长度! 或联系管理员!"
|
| 787 |
final_fallback_error_code = "max_retries_check_context_contact_admin_fallback"
|
| 788 |
logging.error(f"【同步请求】意外退出空回复重试循环。返回最终错误。")
|
|
|
|
| 255 |
accumulated_text_parts = []
|
| 256 |
api_error_yielded = False
|
| 257 |
|
|
|
|
| 258 |
max_500_retries_for_this_call = 5
|
| 259 |
current_500_retry_count = 0
|
| 260 |
|
| 261 |
while current_500_retry_count < max_500_retries_for_this_call:
|
| 262 |
current_500_retry_count += 1
|
| 263 |
+
if current_500_retry_count > 1:
|
| 264 |
logging.info(f"【流式请求子尝试 {current_attempt_num_logging} - 500错误重试 {current_500_retry_count-1}/{max_500_retries_for_this_call-1}】Key: {keymgr.display_key(apikey_for_attempt)}")
|
| 265 |
else:
|
| 266 |
logging.info(f"【流式请求子尝试 {current_attempt_num_logging}】发送到 OnDemand: Session={session_id_for_attempt}, Endpoint={endpoint_id}, Key={keymgr.display_key(apikey_for_attempt)}")
|
| 267 |
|
|
|
|
| 268 |
try:
|
| 269 |
with requests.post(url, json=payload, headers=headers, stream=True, timeout=180) as resp:
|
| 270 |
+
if resp.status_code == 500:
|
| 271 |
logging.warning(f"【OnDemand流错误】(子尝试 {current_attempt_num_logging}, 500重试 {current_500_retry_count}) 收到500错误。Session: {session_id_for_attempt}")
|
| 272 |
if current_500_retry_count >= max_500_retries_for_this_call:
|
| 273 |
logging.error(f"【OnDemand流错误】(子尝试 {current_attempt_num_logging}) 达到500错误最大重试次数。将错误传递给上层。")
|
|
|
|
| 274 |
api_error_yielded = True
|
| 275 |
error_payload = {"error": {"message": f"OnDemand API persistent 500 error after {max_500_retries_for_this_call} retries (Attempt {current_attempt_num_logging}).",
|
| 276 |
"type": "on_demand_persistent_500_error", "code": 500}}
|
| 277 |
yield format_openai_sse_delta(error_payload)
|
| 278 |
yield "data: [DONE]\n\n"
|
| 279 |
return "".join(accumulated_text_parts).strip(), api_error_yielded
|
| 280 |
+
time.sleep(1)
|
| 281 |
+
continue
|
| 282 |
|
| 283 |
+
if resp.status_code != 200:
|
| 284 |
api_error_yielded = True
|
| 285 |
error_text = resp.text
|
| 286 |
logging.error(f"【OnDemand流错误】请求失败 (子尝试 {current_attempt_num_logging})。状态码: {resp.status_code}, Session: {session_id_for_attempt}, 响应: {error_text[:500]}")
|
|
|
|
| 295 |
yield "data: [DONE]\n\n"
|
| 296 |
return "".join(accumulated_text_parts).strip(), api_error_yielded
|
| 297 |
|
|
|
|
| 298 |
first_chunk_sent = False
|
| 299 |
last_line_str = ""
|
| 300 |
for line_bytes in resp.iter_lines():
|
|
|
|
| 352 |
if not api_error_yielded and not last_line_str.startswith("data: [DONE]"):
|
| 353 |
logging.info(f"【OnDemand流】(子尝试 {current_attempt_num_logging}) 流迭代完成,补充发送 [DONE]。Session: {session_id_for_attempt}")
|
| 354 |
yield "data: [DONE]\n\n"
|
| 355 |
+
return "".join(accumulated_text_parts).strip(), api_error_yielded
|
| 356 |
|
| 357 |
except requests.exceptions.RequestException as e_req_inner:
|
|
|
|
| 358 |
logging.error(f"【OnDemand流】(子尝试 {current_attempt_num_logging}) 请求时发生异常: {e_req_inner}, Key: {keymgr.display_key(apikey_for_attempt)}")
|
|
|
|
| 359 |
if current_500_retry_count >= max_500_retries_for_this_call or (hasattr(e_req_inner, 'response') and e_req_inner.response is not None and e_req_inner.response.status_code != 500):
|
| 360 |
raise e_req_inner
|
| 361 |
+
time.sleep(1)
|
|
|
|
|
|
|
| 362 |
|
| 363 |
except Exception as e_inner_unknown:
|
| 364 |
logging.error(f"【OnDemand流】处理流时发生未知��误 (子尝试 {current_attempt_num_logging}): {e_inner_unknown}, Session: {session_id_for_attempt}", exc_info=True)
|
|
|
|
| 370 |
yield "data: [DONE]\n\n"
|
| 371 |
return "".join(accumulated_text_parts).strip(), api_error_yielded
|
| 372 |
|
|
|
|
| 373 |
logging.error(f"【OnDemand流】(子尝试 {current_attempt_num_logging}) 500错误重试循环意外结束。")
|
|
|
|
|
|
|
| 374 |
raise requests.exceptions.RequestException(f"Exhausted internal 500 retries for attempt {current_attempt_num_logging} without success or specific error propagation.")
|
| 375 |
|
| 376 |
|
|
|
|
| 506 |
while empty_retry_attempt_num < max_empty_response_retries:
|
| 507 |
empty_retry_attempt_num += 1
|
| 508 |
accumulated_text_this_attempt = ""
|
| 509 |
+
api_error_in_attempt = False
|
| 510 |
|
| 511 |
if empty_retry_attempt_num > 1:
|
| 512 |
logging.info(f"【流式请求-空回复重试 {empty_retry_attempt_num-1}】获取新Key/Session...")
|
|
|
|
| 542 |
log_attempt_str = f"初始尝试" if empty_retry_attempt_num == 1 else f"空回复重试 {empty_retry_attempt_num-1}"
|
| 543 |
|
| 544 |
try:
|
|
|
|
| 545 |
result_tuple = yield from _execute_one_stream_attempt(
|
| 546 |
current_apikey_for_attempt,
|
| 547 |
current_session_id_for_attempt,
|
|
|
|
| 551 |
f"{log_attempt_str} (Overall attempt {empty_retry_attempt_num})"
|
| 552 |
)
|
| 553 |
accumulated_text_this_attempt = result_tuple[0]
|
| 554 |
+
api_error_in_attempt = result_tuple[1]
|
| 555 |
|
| 556 |
+
except requests.exceptions.RequestException as e_req:
|
| 557 |
log_key_display = keymgr.display_key(current_apikey_for_attempt) if current_apikey_for_attempt else "N/A"
|
| 558 |
status_code_from_exc_stream = None
|
| 559 |
if hasattr(e_req, 'response') and e_req.response is not None:
|
|
|
|
| 570 |
keymgr.mark_bad(current_apikey_for_attempt)
|
| 571 |
|
| 572 |
if empty_retry_attempt_num == 1:
|
|
|
|
|
|
|
| 573 |
raise e_req
|
| 574 |
|
|
|
|
| 575 |
if empty_retry_attempt_num >= max_empty_response_retries:
|
| 576 |
final_error_message = "重试次数过多,请检查上下文长度! 或联系管理员!"
|
| 577 |
final_error_code = "max_retries_check_context_contact_admin"
|
|
|
|
| 580 |
yield "data: [DONE]\n\n"
|
| 581 |
return
|
| 582 |
time.sleep(1)
|
| 583 |
+
continue
|
| 584 |
|
|
|
|
| 585 |
if api_error_in_attempt:
|
|
|
|
|
|
|
| 586 |
logging.warning(f"【流式请求】({log_attempt_str}) 子尝试已处理并流式传输API错误。")
|
| 587 |
+
return
|
| 588 |
|
| 589 |
if accumulated_text_this_attempt:
|
| 590 |
logging.info(f"【流式请求】({log_attempt_str}) 成功获取非空内容。")
|
| 591 |
+
return
|
| 592 |
|
|
|
|
| 593 |
logging.warning(f"【流式请求】({log_attempt_str}) 返回空内容。")
|
| 594 |
if empty_retry_attempt_num >= max_empty_response_retries:
|
| 595 |
final_error_message = "重试次数过多,请检查上下文长度! 或联系管理员!"
|
|
|
|
| 618 |
current_apikey_for_attempt = initial_apikey
|
| 619 |
current_session_id_for_attempt = initial_session_id
|
| 620 |
|
| 621 |
+
ai_response_content = "" # Define ai_response_content outside the try block to ensure it's available for the final empty check
|
| 622 |
+
|
| 623 |
while empty_retry_attempt_num < max_empty_response_retries:
|
| 624 |
empty_retry_attempt_num += 1
|
| 625 |
|
|
|
|
| 654 |
|
| 655 |
log_attempt_str = f"初始尝试" if empty_retry_attempt_num == 1 else f"空回复重试 {empty_retry_attempt_num-1}"
|
| 656 |
|
|
|
|
| 657 |
max_500_retries_for_this_call = 5
|
| 658 |
current_500_retry_count = 0
|
| 659 |
|
| 660 |
+
# Reset ai_response_content for each new attempt (especially for the 500-retry loop)
|
| 661 |
+
ai_response_content = ""
|
| 662 |
+
|
| 663 |
while current_500_retry_count < max_500_retries_for_this_call:
|
| 664 |
current_500_retry_count += 1
|
| 665 |
if current_500_retry_count > 1:
|
|
|
|
| 667 |
else:
|
| 668 |
logging.info(f"【同步请求】({log_attempt_str}, 总尝试 {empty_retry_attempt_num}) Session={current_session_id_for_attempt}, Key={keymgr.display_key(current_apikey_for_attempt)}")
|
| 669 |
|
| 670 |
+
url = f"{ONDEMAND_API_BASE}/sessions/{current_session_id_for_attempt}/query"
|
| 671 |
+
# Corrected: Use query_str and endpoint_id parameters passed to the function
|
| 672 |
+
payload = { "query": query_str, "endpointId": endpoint_id, "pluginIds": [], "responseMode": "sync" }
|
| 673 |
headers = {"apikey": current_apikey_for_attempt, "Content-Type": "application/json"}
|
| 674 |
|
| 675 |
try:
|
|
|
|
| 679 |
logging.warning(f"【OnDemand同步错误】({log_attempt_str}, 500重试 {current_500_retry_count}) 收到500错误。")
|
| 680 |
if current_500_retry_count >= max_500_retries_for_this_call:
|
| 681 |
logging.error(f"【OnDemand同步错误】({log_attempt_str}) 达到500错误最大重试次数。将错误传递给上层。")
|
| 682 |
+
resp.raise_for_status()
|
| 683 |
time.sleep(1)
|
| 684 |
+
continue
|
| 685 |
|
| 686 |
+
resp.raise_for_status()
|
| 687 |
|
|
|
|
| 688 |
response_json = resp.json()
|
| 689 |
if "data" not in response_json or "answer" not in response_json["data"]:
|
| 690 |
logging.error(f"【OnDemand同步错误】响应格式不符合预期 ({log_attempt_str})。Session: {current_session_id_for_attempt}, 响应: {str(response_json)[:500]}")
|
|
|
|
| 703 |
}
|
| 704 |
return jsonify(openai_response_obj) # SUCCESS
|
| 705 |
else:
|
|
|
|
| 706 |
logging.warning(f"【同步请求】({log_attempt_str}, 500重试 {current_500_retry_count}) 返回空回复。")
|
| 707 |
+
break
|
|
|
|
|
|
|
| 708 |
|
| 709 |
+
except requests.exceptions.RequestException as e_req:
|
| 710 |
log_key_display_sync = keymgr.display_key(current_apikey_for_attempt) if current_apikey_for_attempt else "N/A"
|
| 711 |
status_code_from_exc_sync = None
|
| 712 |
if hasattr(e_req, 'response') and e_req.response is not None:
|
|
|
|
| 714 |
|
| 715 |
logging.warning(f"【同步请求】({log_attempt_str}, 500重试 {current_500_retry_count} using key {log_key_display_sync}) 发生请求级错误: {e_req}, Status: {status_code_from_exc_sync}")
|
| 716 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 717 |
if current_500_retry_count >= max_500_retries_for_this_call or status_code_from_exc_sync != 500:
|
| 718 |
if empty_retry_attempt_num == 1:
|
| 719 |
+
raise e_req
|
| 720 |
else:
|
| 721 |
+
raise e_req
|
|
|
|
|
|
|
|
|
|
| 722 |
|
|
|
|
| 723 |
time.sleep(1)
|
| 724 |
+
# Continue to the next iteration of current_500_retry_count loop
|
| 725 |
|
| 726 |
except (ValueError, KeyError, json.JSONDecodeError) as e_parse:
|
| 727 |
logging.error(f"【同步请求】({log_attempt_str}, 500重试 {current_500_retry_count}) 处理响应或格式时出错: {e_parse}", exc_info=True)
|
| 728 |
+
if empty_retry_attempt_num == 1 and current_500_retry_count == 1 :
|
| 729 |
raise requests.exceptions.RequestException(f"Response format error on first attempt: {e_parse}") from e_parse
|
|
|
|
|
|
|
|
|
|
| 730 |
raise requests.exceptions.RequestException(f"Response format error during retry: {e_parse}") from e_parse
|
| 731 |
|
| 732 |
+
# After the 500-retry loop for the current key/session
|
| 733 |
+
if ai_response_content.strip(): # Should have been returned if non-empty
|
| 734 |
+
pass # Should not reach here if content was found
|
| 735 |
+
else: # Content is still empty for this key/session after 500-retries (or if 200 OK but empty)
|
| 736 |
if empty_retry_attempt_num >= max_empty_response_retries:
|
| 737 |
final_error_message = "重试次数过多,请检查上下文长度! 或联系管理员!"
|
| 738 |
final_error_code = "max_retries_check_context_contact_admin"
|
|
|
|
| 746 |
}), 500
|
| 747 |
logging.info(f"【同步请求】空回复(在500-重试循环之后),准备进行下一个空回复尝试。当前总尝试 {empty_retry_attempt_num}/{max_empty_response_retries}")
|
| 748 |
time.sleep(1)
|
| 749 |
+
# Outer loop (empty_retry_attempt_num) will continue to try a new key/session
|
|
|
|
|
|
|
|
|
|
| 750 |
|
|
|
|
| 751 |
final_fallback_error_message = "重试次数过多,请检查上下文长度! 或联系管理员!"
|
| 752 |
final_fallback_error_code = "max_retries_check_context_contact_admin_fallback"
|
| 753 |
logging.error(f"【同步请求】意外退出空回复重试循环。返回最终错误。")
|