binary-husky/gpt_academic · error · ValueError

解析GEMINI消息出错。

Error message

解析GEMINI消息出错。

What it means

ValueError ('解析GEMINI消息出错。') raised when the regex-extracted "text" field from a Gemini stream frame cannot be re-assembled into valid JSON: the code fishes the captured group out of the raw SSE bytes with a regex, wraps it as '{"text": "%s"}', and calls json.loads. If the captured string contains unescaped quotes, control characters, or unicode the naive wrapping can't represent, json.loads throws and this error replaces it. It signals the hand-rolled parser lost against Gemini's escaping, not that Gemini itself errored (error frames take the separate error_match branch).

Source

Thrown at request_llms/bridge_google_gemini.py:36

def predict_no_ui_long_connection(inputs:str, llm_kwargs:dict, history:list=[], sys_prompt:str="", observe_window:list=[],
                                  console_silence:bool=False):
    # 检查API_KEY
    if get_conf("GEMINI_API_KEY") == "":
        raise ValueError(f"请配置 GEMINI_API_KEY。")

    genai = GoogleChatInit(llm_kwargs)
    watch_dog_patience = 5  # 看门狗的耐心, 设置5秒即可
    gpt_replying_buffer = ''
    stream_response = genai.generate_chat(inputs, llm_kwargs, history, sys_prompt)
    for response in stream_response:
        results = response.decode()
        match = re.search(r'"text":\s*"((?:[^"\\]|\\.)*)"', results, flags=re.DOTALL)
        error_match = re.search(r'\"message\":\s*\"(.*?)\"', results, flags=re.DOTALL)
        if match:
            try:
                paraphrase = json.loads('{"text": "%s"}' % match.group(1))
            except:
                raise ValueError(f"解析GEMINI消息出错。")
            buffer = paraphrase['text']
            gpt_replying_buffer += buffer
            if len(observe_window) >= 1:
                observe_window[0] = gpt_replying_buffer
            if len(observe_window) >= 2:
                if (time.time() - observe_window[1]) > watch_dog_patience: raise RuntimeError("程序终止。")
        if error_match:
            raise RuntimeError(f'{gpt_replying_buffer} 对话错误')
    return gpt_replying_buffer

def make_media_input(inputs, image_paths):
    image_base64_array = []
    for image_path in image_paths:
        path = os.path.abspath(image_path)
        inputs = inputs + f'<br/><br/><div align="center"><img src="file={path}"></div>'
        base64 = encode_image(path)
        image_base64_array.append(base64)
    return inputs, image_base64_array

View on GitHub (pinned to d6bde0fa54)

Solutions

  1. Retry the query — transient chunk-boundary splits often parse fine on a second attempt.
  2. Update gpt_academic: newer bridge_google_gemini.py replaced regex fishing with proper full-frame JSON parsing.
  3. If persistent, reduce prompt-induced heavy quoting (ask for plain text instead of JSON/code blocks) to confirm parser escaping is the cause.
  4. Check the proxy chain: intermediary re-chunking of the SSE stream is a common amplifier of partial-frame parse failures.

Example fix

# before (fragile regex reassembly)
paraphrase = json.loads('{"text": "%s"}' % match.group(1))

# after (parse the whole frame)
frame = json.loads(response.decode())
buffer = frame["candidates"][0]["content"]["parts"][0]["text"]
Defensive patterns

Strategy: retry

Type guard

def is_parseable_gemini_text_frame(raw: bytes) -> bool:
    """A frame is safely parseable only if the regex capture survives JSON re-wrapping."""
    import re, json
    text = raw.decode(errors='replace')
    m = re.search(r'"text":\s*"((?:[^"\\]|\\.)*)"', text, flags=re.DOTALL)
    if not m:
        return False
    try:
        json.loads('{"text": "%s"}' % m.group(1))
        return True
    except Exception:
        return False

Try / catch

try:
    result = predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, observe_window)
except ValueError as e:
    if '解析GEMINI消息出错' in str(e):
        time.sleep(1)
        result = predict_no_ui_long_connection(inputs, llm_kwargs, history, sys_prompt, observe_window)  # chunk-boundary splits usually clear on retry
    else:
        raise

Prevention

When it happens

Trigger: Gemini streams text containing characters that break the regex/wrapping contract: raw double quotes with unusual escaping, newlines/backslashes in the captured span, non-ASCII output under odd encodings; also fires on chunk boundaries that split an escaped sequence so the regex capture is malformed.

Common situations: Asking Gemini for code with heavy quote/backslash content; Chinese/multilingual replies with unicode escapes; proxy re-chunking SSE frames so decode() yields partial JSON; older bridge versions' regex parser versus newer Gemini response formats.

Related errors


AI-assisted analysis of binary-husky/gpt_academic@d6bde0fa54 (2026-08-14). Data as JSON: /api/errors/828a898d7af15d34. Report an issue: GitHub.