import gradio as gr from huggingface_hub import InferenceClient MODEL_ID = "openai/gpt-oss-20b" def respond( message: str, history: list[dict], system_message: str, reasoning_effort: str, max_tokens: int, temperature: float, top_p: float, hf_token: gr.OAuthToken | None, ): if hf_token is None or not getattr(hf_token, "token", None): yield "请先点击左侧的“Sign in with Hugging Face”登录,然后再发送消息。" return client = InferenceClient( model=MODEL_ID, provider="auto", token=hf_token.token, ) messages = [] if system_message.strip(): messages.append( { "role": "system", "content": system_message.strip(), } ) # Gradio messages 模式下,history 通常是: # [{"role": "user", "content": "..."}, ...] for item in history: role = item.get("role") content = item.get("content") if role in {"user", "assistant", "system"} and isinstance(content, str): messages.append( { "role": role, "content": content, } ) messages.append( { "role": "user", "content": message, } ) response_text = "" try: stream = client.chat_completion( messages=messages, max_tokens=int(max_tokens), temperature=float(temperature), top_p=float(top_p), stream=True, # 转交给兼容 OpenAI 风格的推理后端。 # 若当前 Provider 不接受该字段,删除 extra_body 即可。 extra_body={ "reasoning_effort": reasoning_effort, }, ) for chunk in stream: if not chunk.choices: continue delta = chunk.choices[0].delta token = getattr(delta, "content", None) if token: response_text += token yield response_text if not response_text: yield "模型没有返回可显示的文本。请稍后重试或更换推理参数。" except Exception as error: error_text = str(error) if "401" in error_text or "unauthorized" in error_text.lower(): yield ( "身份验证失败。请退出后重新登录 Hugging Face," "并确认账户允许调用 Inference Providers。" ) elif "402" in error_text or "payment" in error_text.lower(): yield ( "当前 Hugging Face 账户的推理额度不足," "请检查 Inference Providers 余额或计费设置。" ) elif "429" in error_text or "rate limit" in error_text.lower(): yield "请求过于频繁或免费额度已达到限制,请稍后再试。" else: yield f"调用模型时发生错误:{error_text}" with gr.Blocks(title="GPT-OSS 20B Chat") as demo: gr.Markdown( """ # GPT-OSS 20B Chat 使用 Hugging Face Inference Providers 调用 `openai/gpt-oss-20b`。 请先登录 Hugging Face。推理请求将使用登录用户自己的 HF 账户和额度。 """ ) with gr.Sidebar(): gr.Markdown("### Hugging Face 账户") gr.LoginButton() system_message = gr.Textbox( value="You are a helpful and friendly assistant.", label="System message", lines=4, ) reasoning_effort = gr.Radio( choices=["low", "medium", "high"], value="medium", label="Reasoning effort", ) max_tokens = gr.Slider( minimum=64, maximum=8192, value=1024, step=64, label="Max output tokens", ) temperature = gr.Slider( minimum=0.0, maximum=2.0, value=0.7, step=0.05, label="Temperature", ) top_p = gr.Slider( minimum=0.05, maximum=1.0, value=0.95, step=0.05, label="Top-p", ) gr.ChatInterface( fn=respond, additional_inputs=[ system_message, reasoning_effort, max_tokens, temperature, top_p, ], examples=[ ["请解释 MoE 模型中的总参数和激活参数有什么区别。"], ["用 Python 写一个并发批量请求 API 的示例。"], ], cache_examples=False, ) if __name__ == "__main__": demo.queue( default_concurrency_limit=8, max_size=32, ).launch()