hermes / app.py
cntalk's picture
Update defaults: use Nemotron + CoBuddy (Llama/Hermes rate-limited)
91b36d5 verified
"""
Hermes HF Space - Multi-Model AI Hub (OpenRouter Edition)
多模型对比助手:使用 OpenRouter 免费模型
"""
import gradio as gr
import os
import time
import requests
# OpenRouter 配置
OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY", "")
OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1/chat/completions"
# 预设模型列表(OpenRouter 免费模型)
MODELS = {
"🦙 Llama 3.3 70B (free)": {
"id": "meta-llama/llama-3.3-70b-instruct:free",
"name": "🦙 Llama 3.3 70B",
"context": "66K",
},
"🤖 NVIDIA Nemotron 120B (free)": {
"id": "nvidia/nemotron-3-super-120b-a12b:free",
"name": "🤖 NVIDIA Nemotron 120B",
"context": "1M",
},
"🧠 Nous Hermes 3 405B (free)": {
"id": "nousresearch/hermes-3-llama-3.1-405b:free",
"name": "🧠 Nous Hermes 3 405B",
"context": "128K",
},
"🔧 CoBuddy Code (free)": {
"id": "baidu/cobuddy:free",
"name": "🔧 CoBuddy (百度代码模型)",
"context": "131K",
},
}
SYSTEM_PROMPTS = {
"Default": "",
"Code Assistant": "You are an expert programmer. Write clean, efficient code with brief explanations.",
"中文助手": "你是一个有帮助的中文AI助手,用简洁清晰的语言回答。",
"Summarizer": "You are a text summarization expert. Provide concise, accurate summaries.",
"Creative Writer": "You are a creative writer. Write engaging, imaginative content.",
}
def call_openrouter(model_id: str, prompt: str, max_tokens: int = 384, system: str = "") -> tuple[str, float]:
"""调用 OpenRouter API"""
if not OPENROUTER_API_KEY:
return "⚠️ API key not configured. Please set OPENROUTER_API_KEY in Space secrets.", 0.0
headers = {
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"Content-Type": "application/json",
"HTTP-Referer": "https://cntalk-hermes.hf.space",
"X-Title": "Hermes OpenRouter Hub",
}
messages = []
if system:
messages.append({"role": "system", "content": system})
messages.append({"role": "user", "content": prompt})
payload = {
"model": model_id,
"messages": messages,
"max_tokens": max_tokens,
"temperature": 0.7,
}
try:
start = time.time()
resp = requests.post(
OPENROUTER_BASE_URL,
headers=headers,
json=payload,
timeout=90,
)
elapsed = time.time() - start
if resp.status_code == 200:
result = resp.json()
content = result["choices"][0]["message"]["content"]
return content, elapsed
elif resp.status_code == 429:
return "⚠️ Rate limit exceeded. Please wait a moment or try a different model.", elapsed
else:
error_msg = resp.json().get("error", {}).get("message", resp.text[:150])
return f"⚠️ Error {resp.status_code}: {error_msg}", elapsed
except Exception as e:
return f"⚠️ Request failed: {str(e)[:100]}", 0.0
def format_response(model_name: str, context: str, response: str, elapsed: float) -> str:
emoji = "✅" if not response.startswith("⚠️") else "⚠️"
return f"{emoji} **{model_name}** [ctx:{context}] ({elapsed:.1f}s)\n{response}\n"
def compare_models(user_input: str, model_keys: list, system_key: str = "Default"):
"""对比多个模型的回答"""
if not user_input.strip():
return "⚠️ Please enter a message."
system = SYSTEM_PROMPTS.get(system_key, "")
results = []
for key in model_keys:
model = MODELS.get(key)
if not model:
continue
model_id = model["id"]
model_name = model["name"]
model_context = model["context"]
response, elapsed = call_openrouter(model_id, user_input, system=system)
results.append(format_response(model_name, model_context, response, elapsed))
if not results:
return "⚠️ Please select at least one model."
return "\n---\n".join(results)
def single_chat(model_key: str, user_input: str, system_key: str, history: list):
"""单模型对话(带历史)"""
if not user_input.strip():
return history, ""
model = MODELS.get(model_key, {})
model_id = model.get("id", "")
system = SYSTEM_PROMPTS.get(system_key, "")
# 构建带历史的 prompt
prompt = ""
for h_user, h_bot in history:
prompt += f"User: {h_user}\nAssistant: {h_bot}\n"
prompt += f"User: {user_input}"
response, elapsed = call_openrouter(model_id, prompt, system=system)
history.append((user_input, f"{response}\n\n⏱️ {elapsed:.1f}s"))
return history, ""
# Gradio UI
with gr.Blocks(title="Hermes OpenRouter Hub", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🐠 Hermes OpenRouter Hub
### 多模型 AI 助手 — 同时对比多个开源模型的回答
基于 OpenRouter API,支持 Llama 3.3 / Nemotron / Hermes 3 等免费模型
⚠️ 免费模型有速率限制,如遇报错稍后重试即可
""")
with gr.Tabs():
with gr.TabItem("🔍 模型对比"):
with gr.Row():
with gr.Column(scale=2):
user_input = gr.Textbox(
label="✏️ 输入问题",
placeholder="例如: 解释一下什么是transformer架构",
lines=4,
)
with gr.Row():
system_dropdown = gr.Dropdown(
choices=list(SYSTEM_PROMPTS.keys()),
value="Default",
label="系统提示",
)
compare_btn = gr.Button("🚀 对比模型", variant="primary")
gr.Markdown("**选择要对比的模型:**")
model_checkboxes = gr.CheckboxGroup(
choices=[(v["name"], k) for k, v in MODELS.items()],
value=["🤖 NVIDIA Nemotron 120B (free)", "🔧 CoBuddy Code (free)"],
interactive=True,
)
with gr.Column(scale=3):
output = gr.Markdown("""
*选择模型后点击「对比模型」开始分析*
每个模型独立回答,可对比:
- 回答质量与风格
- 响应速度
- Context 长度差异
💡 免费模型有并发限制,高频使用建议错峰
""")
compare_btn.click(
fn=compare_models,
inputs=[user_input, model_checkboxes, system_dropdown],
outputs=output,
)
with gr.TabItem("💬 单模型对话"):
with gr.Row():
with gr.Column(scale=1):
model_select = gr.Dropdown(
choices=[(v["name"], k) for k, v in MODELS.items()],
value="🤖 NVIDIA Nemotron 120B (free)",
label="选择模型",
)
system_s = gr.Dropdown(
choices=list(SYSTEM_PROMPTS.keys()),
value="Default",
label="系统提示",
)
with gr.Column(scale=3):
chat_history = gr.Chatbot(label="对话历史", height=400)
with gr.Row():
msg_input = gr.Textbox(
placeholder="输入消息...",
scale=4,
lines=2,
)
send_btn = gr.Button("发送", variant="primary", scale=1)
def on_send(msg, history):
return single_chat(model_select.value, msg, system_s.value, history)
send_btn.click(
fn=on_send, inputs=[msg_input, chat_history], outputs=[chat_history, msg_input]
)
msg_input.submit(
fn=on_send, inputs=[msg_input, chat_history], outputs=[chat_history, msg_input]
)
with gr.TabItem("ℹ️ 关于"):
gr.Markdown("""
## 🐠 Hermes OpenRouter Hub
**功能:**
- 🔍 多模型对比:一次提问,同时获得多个模型的回答
- 💬 单模型对话:深入对话某一特定模型
- 🌐 中英文支持
**支持的免费模型:**
| 模型 | 参数量 | Context | 特点 |
|------|--------|---------|------|
| Llama 3.3 70B | 70B | 66K | 高质量多语言 |
| NVIDIA Nemotron 120B | 120B MoE | 1M | 超长上下文 |
| Nous Hermes 3 405B | 405B | 128K | 超大模型 |
| CoBuddy | 1.44B | 131K | 代码专用,百度 |
**限制:** 免费 tier 有速率限制,高频使用请考虑升级或自备 key。
Powered by [OpenRouter](https://openrouter.ai)
""")
# 启动
demo.launch()