Spaces:
Sleeping
Sleeping
File size: 5,820 Bytes
82f18d5 19c5734 82f18d5 19c5734 82f18d5 19c5734 76e29f8 19c5734 76e29f8 19c5734 76e29f8 19c5734 76e29f8 19c5734 76e29f8 19c5734 76e29f8 19c5734 76e29f8 19c5734 76e29f8 19c5734 76e29f8 3d856bc 19c5734 82f18d5 76e29f8 19c5734 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | import gradio as gr
import requests
import os
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
# ========== 从环境变量读取密钥 ==========
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
CEREBRAS_API_KEY = os.getenv("CEREBRAS_API_KEY")
# ========== 模型定义 ==========
LOCAL_MODELS = {
"DistilGPT2 (最快)": "distilgpt2",
"DialoGPT-small (轻量)": "microsoft/DialoGPT-small",
"DialoGPT-medium (均衡)": "microsoft/DialoGPT-medium",
}
OPENROUTER_MODELS = {
"Llama 3.3 70B (免费)": "meta-llama/llama-3.3-70b-instruct:free",
"Nemotron 3 Super (免费)": "nvidia/nemotron-3-super:free",
"Qwen3 Next 80B (免费)": "qwen/qwen3-next-80b:free",
}
CEREBRAS_MODELS = {
"Llama 3.1 8B (Cerebras)": "llama3.1-8b",
}
local_model_cache = {}
def load_local_model(model_key):
if model_key in local_model_cache:
return local_model_cache[model_key]
model_id = LOCAL_MODELS[model_key]
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(model_id)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
local_model_cache[model_key] = (model, tokenizer)
return model, tokenizer
def is_chinese(text):
return any('\u4e00' <= c <= '\u9fff' for c in text)
def local_predict(message, model_key):
if is_chinese(message):
return "⚠️ This model only supports English input. 请使用英文。"
model, tokenizer = load_local_model(model_key)
inputs = tokenizer.encode(message + tokenizer.eos_token, return_tensors='pt')
outputs = model.generate(
inputs,
max_new_tokens=100,
do_sample=True,
temperature=0.7,
repetition_penalty=1.2,
pad_token_id=tokenizer.eos_token_id
)
reply = tokenizer.decode(outputs[0][inputs.shape[-1]:], skip_special_tokens=True)
return reply.strip() or "I'm not sure how to respond."
def openrouter_predict(message, model_name):
if not OPENROUTER_API_KEY:
return "❌ OpenRouter API key 未设置,请在 Space Secrets 中添加 OPENROUTER_API_KEY"
headers = {
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"HTTP-Referer": "https://your-space.hf.space",
"X-Title": "AI ChatBot",
"Content-Type": "application/json"
}
payload = {
"model": model_name,
"messages": [{"role": "user", "content": message}],
"max_tokens": 500,
"temperature": 0.7
}
try:
resp = requests.post("https://openrouter.ai/api/v1/chat/completions", headers=headers, json=payload, timeout=60)
if resp.status_code == 200:
return resp.json()["choices"][0]["message"]["content"]
elif resp.status_code == 402:
return "⚠️ 免费额度已用完或需启用付费模型。"
else:
return f"❌ API 错误 {resp.status_code}"
except Exception as e:
return f"❌ 请求失败: {e}"
def cerebras_predict(message, model_name):
if not CEREBRAS_API_KEY:
return "❌ Cerebras API key 未设置,请在 Space Secrets 中添加 CEREBRAS_API_KEY"
headers = {
"Authorization": f"Bearer {CEREBRAS_API_KEY}",
"Content-Type": "application/json"
}
payload = {
"model": model_name,
"messages": [{"role": "user", "content": message}],
"max_tokens": 500,
"temperature": 0.7
}
try:
resp = requests.post("https://api.cerebras.ai/v1/chat/completions", headers=headers, json=payload, timeout=60)
if resp.status_code == 200:
return resp.json()["choices"][0]["message"]["content"]
else:
return f"❌ Cerebras 错误 {resp.status_code}"
except Exception as e:
return f"❌ 请求失败: {e}"
def predict(message, history, backend, model_choice):
if not message.strip():
return ""
if backend == "本地 CPU 模型 (限英文)":
return local_predict(message, model_choice)
elif backend == "OpenRouter (不限语言)":
return openrouter_predict(message, model_choice)
elif backend == "Cerebras (不限语言)":
return cerebras_predict(message, model_choice)
else:
return "未知后端"
with gr.Blocks(title="多后端 AI 聊天机器人", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🧠 多后端 AI 聊天机器人")
gr.Markdown("**本地 CPU 模型**仅限英文;**OpenRouter / Cerebras** 不限语言,且质量更高。")
with gr.Row():
backend_radio = gr.Radio(
choices=["本地 CPU 模型 (限英文)", "OpenRouter (不限语言)", "Cerebras (不限语言)"],
label="选择后端",
value="本地 CPU 模型 (限英文)"
)
model_dropdown = gr.Dropdown(
choices=list(LOCAL_MODELS.keys()),
label="模型选择",
value=list(LOCAL_MODELS.keys())[2]
)
def update_model_dropdown(backend):
if backend == "本地 CPU 模型 (限英文)":
return gr.update(choices=list(LOCAL_MODELS.keys()), value=list(LOCAL_MODELS.keys())[2], visible=True)
elif backend == "OpenRouter (不限语言)":
return gr.update(choices=list(OPENROUTER_MODELS.keys()), value=list(OPENROUTER_MODELS.keys())[0], visible=True)
else:
return gr.update(choices=list(CEREBRAS_MODELS.keys()), value=list(CEREBRAS_MODELS.keys())[0], visible=True)
backend_radio.change(fn=update_model_dropdown, inputs=backend_radio, outputs=model_dropdown)
chatbot = gr.ChatInterface(
fn=predict,
additional_inputs=[backend_radio, model_dropdown],
title=None,
description="多轮对话,自动记忆上下文。"
)
demo.launch(server_port=7860) |