Skip to content

Commit d2f2163

Browse files
authored
Merge pull request TQZHR#45 from lijirou12/codex/migrate-imagine-to-grok-superimage-1.0-pg7sej
Add grok-superimage model with server-side image config, improve SSE error handling and transient retry logic
2 parents 4c53234 + 978b5bd commit d2f2163

4 files changed

Lines changed: 59 additions & 7 deletions

File tree

app/services/grok/services/chat.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from app.services.grok.services.model import ModelService
2323
from app.services.grok.utils.upload import UploadService
2424
from app.services.grok.utils import process as proc_base
25-
from app.services.grok.utils.retry import pick_token, rate_limited
25+
from app.services.grok.utils.retry import pick_token, rate_limited, transient_upstream
2626
from app.services.reverse.app_chat import AppChatReverse
2727
from app.services.reverse.utils.session import ResettableSession
2828
from app.services.grok.utils.stream import wrap_stream_with_usage
@@ -481,6 +481,13 @@ async def completions(
481481
)
482482
continue
483483

484+
if transient_upstream(e):
485+
logger.warning(
486+
f"Transient upstream error for token {token[:10]}..., "
487+
f"trying next token (attempt {attempt + 1}/{max_token_retries}): {e}"
488+
)
489+
continue
490+
484491
# 非 429 错误,不换 token,直接抛出
485492
raise
486493

app/services/grok/utils/retry.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,24 @@ def rate_limited(error: Exception) -> bool:
4242
return status == 429 or code == "rate_limit_exceeded"
4343

4444

45-
__all__ = ["pick_token", "rate_limited"]
45+
def transient_upstream(error: Exception) -> bool:
46+
"""Whether error is likely transient and safe to retry with another token."""
47+
if not isinstance(error, UpstreamException):
48+
return False
49+
details = error.details or {}
50+
status = details.get("status")
51+
err = str(details.get("error") or error).lower()
52+
transient_status = {408, 500, 502, 503, 504}
53+
if status in transient_status:
54+
return True
55+
timeout_markers = (
56+
"timed out",
57+
"timeout",
58+
"connection reset",
59+
"temporarily unavailable",
60+
"http2",
61+
)
62+
return any(marker in err for marker in timeout_markers)
63+
64+
65+
__all__ = ["pick_token", "rate_limited", "transient_upstream"]

app/services/reverse/app_chat.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,12 @@ async def request(
123123
)
124124

125125
# Curl Config
126-
timeout = max(
127-
float(get_config("chat.timeout") or 0),
128-
float(get_config("video.timeout") or 0),
129-
float(get_config("image.timeout") or 0),
130-
)
126+
timeout = float(get_config("chat.timeout") or 0)
127+
if timeout <= 0:
128+
timeout = max(
129+
float(get_config("video.timeout") or 0),
130+
float(get_config("image.timeout") or 0),
131+
)
131132
browser = get_config("proxy.browser")
132133

133134
async def _do_request():

app/static/admin/js/config.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ const LOCALE_MAP = {
100100
},
101101

102102

103+
"superimage": {
104+
"label": "SuperImage 配置",
105+
"n": { title: "生成数量", desc: "仅用于 grok-superimage-1.0 的服务端统一生成数量(1-10)。" },
106+
"size": { title: "图片尺寸", desc: "仅用于 grok-superimage-1.0 的服务端统一尺寸。" },
107+
"response_format": { title: "响应格式", desc: "仅用于 grok-superimage-1.0 的服务端统一返回格式。" }
108+
},
109+
110+
103111
"asset": {
104112
"label": "资产配置",
105113
"upload_concurrent": { title: "上传并发", desc: "上传接口的最大并发数。推荐 30。" },
@@ -412,6 +420,22 @@ function buildFieldCard(section, key, val) {
412420
{ val: 'url', text: 'URL' }
413421
]);
414422
}
423+
else if (section === 'superimage' && key === 'size') {
424+
built = buildSelectInput(section, key, val, [
425+
{ val: '1024x1024', text: '1024x1024 (1:1)' },
426+
{ val: '1280x720', text: '1280x720 (16:9)' },
427+
{ val: '720x1280', text: '720x1280 (9:16)' },
428+
{ val: '1792x1024', text: '1792x1024 (3:2)' },
429+
{ val: '1024x1792', text: '1024x1792 (2:3)' }
430+
]);
431+
}
432+
else if (section === 'superimage' && key === 'response_format') {
433+
built = buildSelectInput(section, key, val, [
434+
{ val: 'url', text: 'URL' },
435+
{ val: 'b64_json', text: 'B64 JSON' },
436+
{ val: 'base64', text: 'Base64' }
437+
]);
438+
}
415439
else if (Array.isArray(val) || typeof val === 'object') {
416440
built = buildJsonInput(section, key, val);
417441
}

0 commit comments

Comments
 (0)