Spaces:
Running
Running
| 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 | |
| ) | |