cpschat / app.py
yogies's picture
Update app.py
90279d0 verified
raw
history blame
7.84 kB
import gradio as gr
import os
import json
from datetime import datetime, date
from openai import OpenAI
# ----------------------------------------------------------------------
# Helper to read secrets from the HF Space environment
# ----------------------------------------------------------------------
def _secret(key: str, fallback: str = None) -> str:
val = os.getenv(key)
if val is not None:
return val
if fallback is not None:
return fallback
raise RuntimeError(f"Secret '{key}' not found. Please add it to your Space secrets.")
# ----------------------------------------------------------------------
# User Management
# ----------------------------------------------------------------------
def load_users():
"""Load users from secrets or environment variables"""
users = {}
# Try to load from JSON string
users_json = _secret("CHAT_USERS", "{}")
try:
users_data = json.loads(users_json)
for username, password in users_data.items():
users[username] = password
except:
pass
return users
# Load users
VALID_USERS = load_users()
def authenticate_user(username, password):
"""Authenticate user against the valid users dictionary"""
return username in VALID_USERS and VALID_USERS[username] == password
# ----------------------------------------------------------------------
# Configuration
# ----------------------------------------------------------------------
# Available models with their respective API configurations
MODELS = {
# "Qwen3-4B-Thinking-2507": {
# "provider": "huggingface",
# "model_name": "Qwen/Qwen3-4B-Thinking-2507:nscale",
# "api_url": "https://router.huggingface.co/v1"
# },
"Nemotron-nano-9b": {
"provider": "openrouter",
"model_name": "nvidia/nemotron-nano-9b-v2:free",
"api_url": "https://openrouter.ai/api/v1",
},
"Gpt-oss-20b": {
"provider": "openrouter",
"model_name": "openai/gpt-oss-20b:floor",
"api_url": "https://openrouter.ai/api/v1"
},
"Gpt-oss-120b": {
"provider": "openrouter",
"model_name": "openai/gpt-oss-120b:floor",
"api_url": "https://openrouter.ai/api/v1"
}
}
# Get model display names for dropdown
MODEL_NAMES = list(MODELS.keys())
# ----------------------------------------------------------------------
# Core Chat Logic
# ----------------------------------------------------------------------
def respond(
message,
history: list[dict[str, str]],
system_message,
max_tokens,
temperature,
top_p,
selected_model,
):
"""
Handle chat responses using the selected model
"""
try:
# Check expiration (optional - remove if not needed)
# end_date = datetime.strptime(_secret("END_DATE", "2026-12-31"), "%Y-%m-%d").date()
# if date.today() > end_date:
# yield "Chatbot has expired."
# return
# Get model configuration
model_config = MODELS[selected_model]
provider = model_config["provider"]
# Get API key based on provider
if provider == "huggingface":
api_key = _secret("HF_TOKEN")
else: # openrouter
api_key = _secret("OPENROUTER_KEY")
# Configure client
client = OpenAI(
base_url=model_config["api_url"],
api_key=api_key,
reasoning_effort = "high"
)
# Prepare messages
messages = [{"role": "system", "content": system_message}]
messages.extend(history)
messages.append({"role": "user", "content": message})
# Make the API call
response = client.chat.completions.create(
model=model_config["model_name"],
messages=messages,
max_tokens=max_tokens,
# temperature=temperature,
# top_p=top_p,
stream=False,
)
# Stream the response
full_response = response.choices[0].content
match = re.search(r'(</think>)([\s\S]*)', full_response, re.MULTILINE)
if match:
filtered_response = match.group(2).strip()
print(f"--- [Private Logic] Filtered response (after </think>) ---")
print(f"Filtered length: {len(filtered_response)}")
print(f"Filtered preview: {filtered_response[:300]}...")
return filtered_response
else:
print(f"--- [Private Logic] No '</think>' marker found, returning full response ---")
return full_response
except Exception as e:
print(f"Error in respond function: {e}")
yield f"Error: {str(e)}"
# ----------------------------------------------------------------------
# Custom Auth Function for Gradio
# ----------------------------------------------------------------------
def gradio_auth(username, password):
"""Custom authentication function for Gradio"""
return authenticate_user(username, password)
# ----------------------------------------------------------------------
# UI Layout
# ----------------------------------------------------------------------
# Tips section
tips_md = """
"""
# Footer
footer_md = """
---
**Providers**: Hugging Face Inference API + OpenRouter, dipilih providers yang tidak menggunakan prompt untuk training data.
"""
# Create the chat interface
with gr.Blocks(
title="Multi-Model Chat Interface",
theme=gr.themes.Soft()
) as demo:
gr.Markdown("# AI Chat")
gr.Markdown("Model yang digunakan gratis. Data tidak digunakan untuk training.")
# Model selection and settings in sidebar
with gr.Sidebar():
gr.Markdown("### ⚙️ Configuration")
# Model selection
selected_model = gr.Dropdown(
choices=MODEL_NAMES,
value=MODEL_NAMES[0],
label="Select Model",
info="Choose which AI model to use"
)
# Display current user (if available)
current_user = gr.Textbox(
label="Current User",
value="Authenticated User",
interactive=False,
visible=False # Hide by default, can set to True if you want to show
)
# Advanced settings
with gr.Accordion("Advanced Settings", open=False):
system_message = gr.Textbox(
value="Respon dalam Bahasa Indonesia.",
label="System Message",
info="Controls the AI's behavior and personality"
)
max_tokens = gr.Slider(
minimum=1, maximum=8096, value=4096, step=1,
label="Max New Tokens",
info="Jumlah token respon maksimum."
)
# Main chat interface
chatbot = gr.ChatInterface(
respond,
type="messages",
additional_inputs=[
system_message,
max_tokens,
selected_model,
],
examples=[
[""],
["Explain quantum computing in simple terms"],
["What are the advantages of using open-source AI models?"]
],
cache_examples=False,
)
# Tips and footer
gr.Markdown(tips_md)
gr.Markdown(footer_md)
# ----------------------------------------------------------------------
# Launch with Custom Auth
# ----------------------------------------------------------------------
if __name__ == "__main__":
demo.launch(
auth=gradio_auth, # Use our custom auth function
auth_message="Please login to access the chat interface",
server_name="0.0.0.0",
ssr_mode=False,
server_port=7860,
show_error=True
)