binary-husky/gpt_academic · error · RuntimeError

意外Json结构:

Error message

意外Json结构:{delta}

What it means

RuntimeError('意外Json结构:'+delta) raised when a stream delta from bridge_openrouter is neither the has_content nor the has_role shape - i.e. decode_chunk found a valid choices[0].delta dict, but it contains unexpected keys only (no 'content', no 'role'). This is the bridge's guard against non-standard OpenAI-compatible providers that inject extra fields or change the delta schema.

Solutions

  1. Inspect the delta printed in the exception to see which unexpected field the provider sends
  2. Switch to a model/provider whose deltas only carry role/content, or extend decode_chunk to whitelist the extra field (e.g. map reasoning_content into content)
  3. Update the bridge to a version that tolerates extra delta keys instead of raising
  4. Disable function-calling / tool parameters if the provider echoes them into deltas

Example fix

# before
else: raise RuntimeError("意外Json结构:"+delta)

# after
elif 'reasoning_content' in delta:
    result += delta['reasoning_content']
else:
    raise RuntimeError("意外Json结构:" + str(delta))
Defensive patterns

Strategy: type-guard

Type guard

def delta_is_supported(delta: dict) -> bool:
    """True when the bridge can consume this delta shape."""
    return isinstance(delta, dict) and ('content' in delta or 'role' in delta)

Try / catch

try:
    result = predict_no_ui_long_connection(...)
except RuntimeError as e:
    if '意外Json结构' in str(e):
        unsupported = e.args[0].split('意外Json结构:')[-1]
        logging.warning('provider sent unsupported delta keys: %s', unsupported)
        switch_to_standard_provider()
    raise

Prevention

When it happens

Trigger: Provider sends delta with only fields like {'reasoning_content': ...} or {'tool_calls': ...}; third-party relay inserting custom metadata keys; new API surface (function calling, reasoning models) not handled by this older bridge.

Common situations: Routing OpenRouter to reasoning models (e.g. deepseek-r1 style) whose deltas carry reasoning fields; providers with bespoke SSE extensions; model versions adding new delta fields.

Related errors


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

Appendix: source

Thrown at request_llms/bridge_openrouter.py:200

        if ('data: [DONE]' in chunk_decoded): break # api2d 正常完成
        # 提前读取一些信息 (用于判断异常)
        json_data = chunkjson['choices'][0]
        delta = json_data["delta"]
        if len(delta) == 0: break
        if (not has_content) and has_role: continue
        if (not has_content) and (not has_role): continue # raise RuntimeError("发现不标准的第三方接口:"+delta)
        if has_content: # has_role = True/False
            result += delta["content"]
            if not console_silence: print(delta["content"], end='')
            if observe_window is not None:
                # 观测窗,把已经获取的数据显示出去
                if len(observe_window) >= 1:
                    observe_window[0] += delta["content"]
                # 看门狗,如果超过期限没有喂狗,则终止
                if len(observe_window) >= 2:
                    if (time.time()-observe_window[1]) > watch_dog_patience:
                        raise RuntimeError("用户取消了程序。")
        else: raise RuntimeError("意外Json结构:"+delta)
    if json_data and json_data['finish_reason'] == 'content_filter':
        raise RuntimeError("由于提问含不合规内容被Azure过滤。")
    if json_data and json_data['finish_reason'] == 'length':
        raise ConnectionAbortedError("正常结束,但显示Token不足,导致输出不完整,请削减单次输入的文本量。")
    return result


def predict(inputs:str, llm_kwargs:dict, plugin_kwargs:dict, chatbot:ChatBotWithCookies,
            history:list=[], system_prompt:str='', stream:bool=True, additional_fn:str=None):
    """
    发送至chatGPT,流式获取输出。
    用于基础的对话功能。
    inputs 是本次问询的输入
    top_p, temperature是chatGPT的内部调优参数
    history 是之前的对话列表(注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误)
    chatbot 为WebUI中显示的对话列表,修改它,然后yield出去,可以直接修改对话界面内容
    additional_fn代表点击的哪个按钮,按钮见functional.py
    """

View on GitHub (pinned to d6bde0fa54)