milwright commited on
Commit
df94830
·
0 Parent(s):

Initial commit

Browse files
Files changed (5) hide show
  1. .gitattributes +35 -0
  2. .gitignore +26 -0
  3. README.md +30 -0
  4. app.py +620 -0
  5. requirements.txt +4 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Environment variables
2
+ .env
3
+ .env.local
4
+
5
+ # Python
6
+ __pycache__/
7
+ *.py[cod]
8
+ *$py.class
9
+ *.so
10
+ .Python
11
+ env/
12
+ venv/
13
+ ENV/
14
+
15
+ # IDE
16
+ .vscode/
17
+ .idea/
18
+ *.swp
19
+ *.swo
20
+
21
+ # OS
22
+ .DS_Store
23
+ Thumbs.db
24
+
25
+ # Logs
26
+ *.log
README.md ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Chat UI Helper
3
+ emoji: 💻
4
+ colorFrom: gray
5
+ colorTo: red
6
+ sdk: gradio
7
+ sdk_version: 5.34.0
8
+ app_file: app.py
9
+ pinned: true
10
+ thumbnail: >-
11
+ https://cdn-uploads.huggingface.co/production/uploads/65a0caa15dfd8b9b1f3aa3d3/8cruZmIioPrYoTN8o-wcE.png
12
+ short_description: Configure, download, and deploy a simple chat interface
13
+ ---
14
+
15
+ # Chat UI Helper
16
+
17
+ A tool to help you create and configure chat interfaces for HuggingFace Spaces.
18
+
19
+ ## Features
20
+
21
+ 1. **Spaces Configuration**: Generate ready-to-deploy packages for custom chat interfaces
22
+ 2. **Chat Support**: Get chat configuration support from Gemma-2-27B
23
+
24
+ ## Setup
25
+
26
+ Set your OpenRouter API key as a secret:
27
+ - Go to Settings → Variables and secrets
28
+ - Add secret: `OPENROUTER_API_KEY`
29
+
30
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,620 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ import zipfile
4
+ import io
5
+ import os
6
+ from datetime import datetime
7
+ from dotenv import load_dotenv
8
+ import requests
9
+ from bs4 import BeautifulSoup
10
+
11
+ # Load environment variables from .env file
12
+ load_dotenv()
13
+
14
+ # Template for generated space app (based on mvp_simple.py)
15
+ SPACE_TEMPLATE = '''import gradio as gr
16
+ import os
17
+ import requests
18
+ import json
19
+ from bs4 import BeautifulSoup
20
+
21
+ # Configuration
22
+ SPACE_NAME = "{name}"
23
+ SPACE_DESCRIPTION = "{description}"
24
+ SYSTEM_PROMPT = """{system_prompt}"""
25
+ MODEL = "{model}"
26
+ GROUNDING_URLS = {grounding_urls}
27
+
28
+ # Get API key from environment - customizable variable name
29
+ API_KEY = os.environ.get("{api_key_var}")
30
+
31
+ def fetch_url_content(url):
32
+ """Fetch and extract text content from a URL"""
33
+ try:
34
+ response = requests.get(url, timeout=10)
35
+ response.raise_for_status()
36
+ soup = BeautifulSoup(response.content, 'html.parser')
37
+
38
+ # Remove script and style elements
39
+ for script in soup(["script", "style"]):
40
+ script.decompose()
41
+
42
+ # Get text content
43
+ text = soup.get_text()
44
+
45
+ # Clean up whitespace
46
+ lines = (line.strip() for line in text.splitlines())
47
+ chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
48
+ text = ' '.join(chunk for chunk in chunks if chunk)
49
+
50
+ # Truncate to ~4000 characters
51
+ if len(text) > 4000:
52
+ text = text[:4000] + "..."
53
+
54
+ return text
55
+ except Exception as e:
56
+ return f"Error fetching {{url}}: {{str(e)}}"
57
+
58
+ def get_grounding_context():
59
+ """Fetch context from grounding URLs"""
60
+ if not GROUNDING_URLS:
61
+ return ""
62
+
63
+ context_parts = []
64
+ for i, url in enumerate(GROUNDING_URLS, 1):
65
+ if url.strip():
66
+ content = fetch_url_content(url.strip())
67
+ context_parts.append(f"Context from URL {{i}} ({{url}}):\\n{{content}}")
68
+
69
+ if context_parts:
70
+ return "\\n\\n" + "\\n\\n".join(context_parts) + "\\n\\n"
71
+ return ""
72
+
73
+ def generate_response(message, history):
74
+ """Generate response using OpenRouter API"""
75
+
76
+ if not API_KEY:
77
+ return "Please set your {api_key_var} in the Space settings."
78
+
79
+ # Get grounding context
80
+ grounding_context = get_grounding_context()
81
+
82
+ # Build enhanced system prompt with grounding context
83
+ enhanced_system_prompt = SYSTEM_PROMPT + grounding_context
84
+
85
+ # Build messages array for the API
86
+ messages = [{{"role": "system", "content": enhanced_system_prompt}}]
87
+
88
+ # Add conversation history - compatible with Gradio 5.x format
89
+ for chat in history:
90
+ if isinstance(chat, dict):
91
+ # New format: {{"role": "user", "content": "..."}} or {{"role": "assistant", "content": "..."}}
92
+ messages.append(chat)
93
+ else:
94
+ # Legacy format: ("user msg", "bot msg")
95
+ user_msg, bot_msg = chat
96
+ messages.append({{"role": "user", "content": user_msg}})
97
+ if bot_msg:
98
+ messages.append({{"role": "assistant", "content": bot_msg}})
99
+
100
+ # Add current message
101
+ messages.append({{"role": "user", "content": message}})
102
+
103
+ # Make API request
104
+ try:
105
+ response = requests.post(
106
+ url="https://openrouter.ai/api/v1/chat/completions",
107
+ headers={{
108
+ "Authorization": f"Bearer {{API_KEY}}",
109
+ "Content-Type": "application/json"
110
+ }},
111
+ json={{
112
+ "model": MODEL,
113
+ "messages": messages,
114
+ "temperature": {temperature},
115
+ "max_tokens": {max_tokens}
116
+ }}
117
+ )
118
+
119
+ if response.status_code == 200:
120
+ return response.json()['choices'][0]['message']['content']
121
+ else:
122
+ return f"Error: {{response.status_code}} - {{response.text}}"
123
+
124
+ except Exception as e:
125
+ return f"Error: {{str(e)}}"
126
+
127
+ # Create simple Gradio interface using ChatInterface
128
+ demo = gr.ChatInterface(
129
+ fn=generate_response,
130
+ title=SPACE_NAME,
131
+ description=SPACE_DESCRIPTION,
132
+ examples={examples}
133
+ )
134
+
135
+ if __name__ == "__main__":
136
+ demo.launch()
137
+ '''
138
+
139
+ # Available models
140
+ MODELS = [
141
+ "google/gemma-3-27b-it",
142
+ <<<<<<< HEAD
143
+ "mistralai/mixtral-8x7b-instruct",
144
+ "meta-llama/llama-3.1-70b-instruct",
145
+ "anthropic/claude-3.5-haiku",
146
+ "nvidia/nemotron-4-340b-instruct",
147
+ "openai/gpt-3.5-turbo"
148
+ =======
149
+ "google/gemini-2.0-flash-001",
150
+ "mistralai/mistral-medium",
151
+ "openai/gpt-4o-nano",
152
+ "anthropic/claude-3.5-haiku"
153
+ >>>>>>> c997ea6 (Update model selection to five current models and remove cost information)
154
+ ]
155
+
156
+ def fetch_url_content(url):
157
+ """Fetch and extract text content from a URL"""
158
+ try:
159
+ response = requests.get(url, timeout=10)
160
+ response.raise_for_status()
161
+ soup = BeautifulSoup(response.content, 'html.parser')
162
+
163
+ # Remove script and style elements
164
+ for script in soup(["script", "style"]):
165
+ script.decompose()
166
+
167
+ # Get text content
168
+ text = soup.get_text()
169
+
170
+ # Clean up whitespace
171
+ lines = (line.strip() for line in text.splitlines())
172
+ chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
173
+ text = ' '.join(chunk for chunk in chunks if chunk)
174
+
175
+ # Truncate to ~4000 characters
176
+ if len(text) > 4000:
177
+ text = text[:4000] + "..."
178
+
179
+ return text
180
+ except Exception as e:
181
+ return f"Error fetching {url}: {str(e)}"
182
+
183
+ def get_grounding_context(urls):
184
+ """Fetch context from grounding URLs"""
185
+ if not urls:
186
+ return ""
187
+
188
+ context_parts = []
189
+ for i, url in enumerate(urls, 1):
190
+ if url and url.strip():
191
+ content = fetch_url_content(url.strip())
192
+ context_parts.append(f"Context from URL {i} ({url}):\n{content}")
193
+
194
+ if context_parts:
195
+ return "\n\n" + "\n\n".join(context_parts) + "\n\n"
196
+ return ""
197
+
198
+ def create_readme(config):
199
+ """Generate README with deployment instructions"""
200
+ return f"""---
201
+ title: {config['name']}
202
+ emoji: 🤖
203
+ colorFrom: blue
204
+ colorTo: red
205
+ sdk: gradio
206
+ sdk_version: 4.32.0
207
+ app_file: app.py
208
+ pinned: false
209
+ ---
210
+
211
+ # {config['name']}
212
+
213
+ {config['description']}
214
+
215
+ ## Quick Deploy to HuggingFace Spaces
216
+
217
+ ### Step 1: Create the Space
218
+ 1. Go to https://huggingface.co/spaces
219
+ 2. Click "Create new Space"
220
+ 3. Choose a name for your Space
221
+ 4. Select **Gradio** as the SDK
222
+ 5. Set visibility (Public/Private)
223
+ 6. Click "Create Space"
224
+
225
+ ### Step 2: Upload Files
226
+ 1. In your new Space, click "Files" tab
227
+ 2. Upload these files from the zip:
228
+ - `app.py`
229
+ - `requirements.txt`
230
+ 3. Wait for "Building" to complete
231
+
232
+ ### Step 3: Add API Key
233
+ 1. Go to Settings (gear icon)
234
+ 2. Click "Variables and secrets"
235
+ 3. Click "New secret"
236
+ 4. Name: `{config['api_key_var']}`
237
+ 5. Value: Your OpenRouter API key
238
+ 6. Click "Add"
239
+
240
+ ### Step 4: Get Your API Key
241
+ 1. Go to https://openrouter.ai/keys
242
+ 2. Sign up/login if needed
243
+ 3. Click "Create Key"
244
+ 4. Copy the key (starts with `sk-or-`)
245
+
246
+ ### Step 5: Test Your Space
247
+ - Go back to "App" tab
248
+ - Your Space should be running!
249
+ - Try the example prompts or ask a question
250
+
251
+ ## Configuration
252
+
253
+ - **Model**: {config['model']}
254
+ - **Temperature**: {config['temperature']}
255
+ - **Max Tokens**: {config['max_tokens']}
256
+ - **API Key Variable**: {config['api_key_var']}
257
+
258
+ ## Customization
259
+
260
+ To modify your Space:
261
+ 1. Edit `app.py` in your Space
262
+ 2. Update configuration variables at the top
263
+ 3. Changes deploy automatically
264
+
265
+ ## Troubleshooting
266
+
267
+ - **"Please set your {config['api_key_var']}"**: Add the secret in Space settings
268
+ - **Error 401**: Invalid API key or no credits
269
+ - **Error 429**: Rate limit - wait and try again
270
+ - **Build failed**: Check requirements.txt formatting
271
+
272
+ ## More Help
273
+
274
+ - HuggingFace Spaces: https://huggingface.co/docs/hub/spaces
275
+ - OpenRouter Docs: https://openrouter.ai/docs
276
+ - Gradio Docs: https://gradio.app/docs
277
+
278
+ ---
279
+
280
+ Generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} with Chat U/I Helper
281
+ """
282
+
283
+ def create_requirements():
284
+ """Generate requirements.txt"""
285
+ return "gradio==4.44.1\nrequests==2.32.3\nbeautifulsoup4==4.12.3"
286
+
287
+ def generate_zip(name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, url1="", url2="", url3="", url4=""):
288
+ """Generate deployable zip file"""
289
+
290
+ # Process examples
291
+ if examples_text and examples_text.strip():
292
+ examples_list = [ex.strip() for ex in examples_text.split('\n') if ex.strip()]
293
+ examples_json = json.dumps(examples_list)
294
+ else:
295
+ examples_json = json.dumps([
296
+ "Hello! How can you help me?",
297
+ "Tell me something interesting",
298
+ "What can you do?"
299
+ ])
300
+
301
+ # Process grounding URLs
302
+ grounding_urls = []
303
+ for url in [url1, url2, url3, url4]:
304
+ if url and url.strip():
305
+ grounding_urls.append(url.strip())
306
+
307
+ # Create config
308
+ config = {
309
+ 'name': name,
310
+ 'description': description,
311
+ 'system_prompt': system_prompt,
312
+ 'model': model,
313
+ 'api_key_var': api_key_var,
314
+ 'temperature': temperature,
315
+ 'max_tokens': int(max_tokens),
316
+ 'examples': examples_json,
317
+ 'grounding_urls': json.dumps(grounding_urls)
318
+ }
319
+
320
+ # Generate files
321
+ app_content = SPACE_TEMPLATE.format(**config)
322
+ readme_content = create_readme(config)
323
+ requirements_content = create_requirements()
324
+
325
+ # Create zip file with clean naming
326
+ filename = f"{name.lower().replace(' ', '_').replace('-', '_')}.zip"
327
+
328
+ # Create zip in memory and save to disk
329
+ zip_buffer = io.BytesIO()
330
+ with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
331
+ zip_file.writestr('app.py', app_content)
332
+ zip_file.writestr('requirements.txt', requirements_content)
333
+ zip_file.writestr('README.md', readme_content)
334
+ zip_file.writestr('config.json', json.dumps(config, indent=2))
335
+
336
+ # Write zip to file
337
+ zip_buffer.seek(0)
338
+ with open(filename, 'wb') as f:
339
+ f.write(zip_buffer.getvalue())
340
+
341
+ return filename
342
+
343
+ # Define callback functions outside the interface
344
+ def on_generate(name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, url1, url2, url3, url4):
345
+ if not name or not name.strip():
346
+ return gr.update(value="Error: Please provide a Space Title", visible=True), gr.update(visible=False)
347
+
348
+ if not system_prompt or not system_prompt.strip():
349
+ return gr.update(value="Error: Please provide a System Prompt", visible=True), gr.update(visible=False)
350
+
351
+ try:
352
+ filename = generate_zip(name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, url1, url2, url3, url4)
353
+
354
+ success_msg = f"""**Deployment package ready!**
355
+
356
+ **File**: `{filename}`
357
+
358
+ **What's included:**
359
+ - `app.py` - Ready-to-deploy chat interface
360
+ - `requirements.txt` - Dependencies
361
+ - `README.md` - Step-by-step deployment guide
362
+ - `config.json` - Configuration backup
363
+
364
+ **Next steps:**
365
+ 1. Download the zip file below
366
+ 2. Follow the README instructions to deploy on HuggingFace Spaces
367
+ 3. Set your `{api_key_var}` secret in Space settings
368
+
369
+ **Your Space will be live in minutes!**"""
370
+
371
+ return gr.update(value=success_msg, visible=True), gr.update(value=filename, visible=True)
372
+
373
+ except Exception as e:
374
+ return gr.update(value=f"Error: {str(e)}", visible=True), gr.update(visible=False)
375
+
376
+ def respond(message, chat_history, url1="", url2="", url3="", url4=""):
377
+ # Make actual API request to OpenRouter
378
+ import os
379
+ import requests
380
+
381
+ # Get API key from environment
382
+ api_key = os.environ.get("OPENROUTER_API_KEY")
383
+
384
+ if not api_key:
385
+ response = "Please set your OPENROUTER_API_KEY in the Space settings to use the chat support."
386
+ chat_history.append([message, response])
387
+ return "", chat_history
388
+
389
+ # Get grounding context from URLs
390
+ grounding_urls = [url1, url2, url3, url4]
391
+ grounding_context = get_grounding_context(grounding_urls)
392
+
393
+ # Build enhanced system prompt with grounding context
394
+ base_system_prompt = """You are an expert assistant specializing in Gradio configurations for HuggingFace Spaces. You have deep knowledge of:
395
+ - Gradio interface components and layouts
396
+ - HuggingFace Spaces configuration (YAML frontmatter, secrets, environment variables)
397
+ - Deployment best practices for Gradio apps on HuggingFace
398
+ - Space settings, SDK versions, and hardware requirements
399
+ - Troubleshooting common Gradio and HuggingFace Spaces issues
400
+ - Integration with various APIs and models through Gradio interfaces
401
+
402
+ Provide specific, technical guidance focused on Gradio implementation details and HuggingFace Spaces deployment. Include code examples when relevant. Keep responses concise and actionable."""
403
+
404
+ enhanced_system_prompt = base_system_prompt + grounding_context
405
+
406
+ # Build conversation history for API
407
+ messages = [{
408
+ "role": "system",
409
+ "content": enhanced_system_prompt
410
+ }]
411
+
412
+ # Add conversation history - Gradio 4.x uses list/tuple format
413
+ for chat in chat_history:
414
+ if isinstance(chat, (list, tuple)) and len(chat) >= 2:
415
+ user_msg, assistant_msg = chat[0], chat[1]
416
+ if user_msg:
417
+ messages.append({"role": "user", "content": user_msg})
418
+ if assistant_msg:
419
+ messages.append({"role": "assistant", "content": assistant_msg})
420
+
421
+ # Add current message
422
+ messages.append({"role": "user", "content": message})
423
+
424
+ try:
425
+ # Make API request to OpenRouter
426
+ response = requests.post(
427
+ url="https://openrouter.ai/api/v1/chat/completions",
428
+ headers={
429
+ "Authorization": f"Bearer {api_key}",
430
+ "Content-Type": "application/json"
431
+ },
432
+ json={
433
+ "model": "google/gemma-3-27b-it",
434
+ "messages": messages,
435
+ "temperature": 0.7,
436
+ "max_tokens": 500
437
+ }
438
+ )
439
+
440
+ if response.status_code == 200:
441
+ assistant_response = response.json()['choices'][0]['message']['content']
442
+ else:
443
+ assistant_response = f"Error: {response.status_code} - {response.text}"
444
+
445
+ except Exception as e:
446
+ assistant_response = f"Error: {str(e)}"
447
+
448
+ chat_history.append([message, assistant_response])
449
+ return "", chat_history
450
+
451
+ def clear_chat():
452
+ return "", []
453
+
454
+ # Create Gradio interface with proper tab structure
455
+ with gr.Blocks(title="Chat U/I Helper") as demo:
456
+ with gr.Tabs():
457
+ with gr.Tab("Spaces Configuration"):
458
+ gr.Markdown("# Spaces Configuration")
459
+ gr.Markdown("Convert custom assistants from HuggingChat into chat interfaces with HuggingFace Spaces. Configure and download everything needed to deploy a simple HF space using Gradio.")
460
+
461
+ with gr.Column():
462
+ name = gr.Textbox(
463
+ label="Space Title",
464
+ placeholder="My Course Helper",
465
+ value="My Custom Space"
466
+ )
467
+
468
+ description = gr.Textbox(
469
+ label="Space Description",
470
+ placeholder="A customizable AI chat interface for...",
471
+ lines=2,
472
+ value="An AI research assistant tailored for academic inquiry and scholarly dialogue"
473
+ )
474
+
475
+ model = gr.Dropdown(
476
+ label="Model",
477
+ choices=MODELS,
478
+ value=MODELS[0],
479
+ info="Choose based on your needs and budget"
480
+ )
481
+
482
+ api_key_var = gr.Textbox(
483
+ label="API Key Variable Name",
484
+ value="OPENROUTER_API_KEY",
485
+ info="Name for the secret in HuggingFace Space settings"
486
+ )
487
+
488
+ system_prompt = gr.Textbox(
489
+ label="System Prompt",
490
+ placeholder="You are a research assistant...",
491
+ lines=4,
492
+ value="You are a knowledgeable academic research assistant. Provide thoughtful, evidence-based guidance for scholarly work, literature reviews, and academic writing. Support students and researchers with clear explanations and critical thinking."
493
+ )
494
+
495
+ examples_text = gr.Textbox(
496
+ label="Example Prompts (one per line)",
497
+ placeholder="Hello! How can you help me?\nWhat's the weather like?\nExplain quantum computing",
498
+ lines=3,
499
+ info="These will appear as clickable examples in the chat interface"
500
+ )
501
+
502
+ gr.Markdown("### URL Grounding (Optional)")
503
+ gr.Markdown("Add up to 4 URLs to provide context. Content will be fetched and added to the system prompt.")
504
+
505
+ url1 = gr.Textbox(
506
+ label="URL 1",
507
+ placeholder="https://example.com/page1",
508
+ info="First URL for context grounding"
509
+ )
510
+
511
+ url2 = gr.Textbox(
512
+ label="URL 2",
513
+ placeholder="https://example.com/page2",
514
+ info="Second URL for context grounding"
515
+ )
516
+
517
+ url3 = gr.Textbox(
518
+ label="URL 3",
519
+ placeholder="https://example.com/page3",
520
+ info="Third URL for context grounding"
521
+ )
522
+
523
+ url4 = gr.Textbox(
524
+ label="URL 4",
525
+ placeholder="https://example.com/page4",
526
+ info="Fourth URL for context grounding"
527
+ )
528
+
529
+ with gr.Row():
530
+ temperature = gr.Slider(
531
+ label="Temperature",
532
+ minimum=0,
533
+ maximum=2,
534
+ value=0.7,
535
+ step=0.1,
536
+ info="Higher = more creative, Lower = more focused"
537
+ )
538
+
539
+ max_tokens = gr.Slider(
540
+ label="Max Response Tokens",
541
+ minimum=50,
542
+ maximum=4096,
543
+ value=1024,
544
+ step=50
545
+ )
546
+
547
+ generate_btn = gr.Button("Generate Deployment Package", variant="primary")
548
+
549
+ status = gr.Markdown(visible=False)
550
+ download_file = gr.File(label="Download your zip package", visible=False)
551
+
552
+ # Connect the generate button
553
+ generate_btn.click(
554
+ on_generate,
555
+ inputs=[name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, url1, url2, url3, url4],
556
+ outputs=[status, download_file]
557
+ )
558
+
559
+ with gr.Tab("Chat Support"):
560
+ gr.Markdown("# Chat Support")
561
+ gr.Markdown("Get personalized guidance on configuring chat assistants as HuggingFace Spaces for educational & research purposes.")
562
+
563
+ # Meta chat interface
564
+ with gr.Column():
565
+ chatbot = gr.Chatbot(
566
+ value=[],
567
+ label="Chat Support Assistant",
568
+ height=400
569
+ )
570
+ msg = gr.Textbox(
571
+ label="Ask about configuring chat UIs for courses, research, or custom HuggingFace Spaces",
572
+ placeholder="How can I configure a chat UI for my senior seminar?",
573
+ lines=2
574
+ )
575
+
576
+ with gr.Accordion("URL Grounding (Optional)", open=False):
577
+ gr.Markdown("Add URLs to provide additional context for more informed responses")
578
+ chat_url1 = gr.Textbox(
579
+ label="URL 1",
580
+ value="https://huggingface.co/docs/hub/en/spaces-overview",
581
+ info="HuggingFace Spaces Overview"
582
+ )
583
+ chat_url2 = gr.Textbox(
584
+ label="URL 2",
585
+ value="https://huggingface.co/docs/hub/en/spaces-config-reference",
586
+ info="Spaces Configuration Reference"
587
+ )
588
+ chat_url3 = gr.Textbox(
589
+ label="URL 3",
590
+ value="https://huggingface.co/docs/hub/en/spaces-settings",
591
+ info="Spaces Settings Documentation"
592
+ )
593
+ chat_url4 = gr.Textbox(
594
+ label="URL 4",
595
+ value="https://huggingface.co/docs/hub/en/spaces-sdks-gradio",
596
+ info="Gradio SDK for Spaces"
597
+ )
598
+ with gr.Row():
599
+ submit = gr.Button("Send", variant="primary")
600
+ clear = gr.Button("Clear")
601
+
602
+ gr.Examples(
603
+ examples=[
604
+ "How do I set up a course assistant?",
605
+ "Which model should I use?",
606
+ "What's a good system prompt?",
607
+ "Why Gradio? What is it?",
608
+ "How do I customize the chat interface?",
609
+ "Can you help me troubleshoot?",
610
+ ],
611
+ inputs=msg
612
+ )
613
+
614
+ # Connect the chat functionality
615
+ submit.click(respond, [msg, chatbot, chat_url1, chat_url2, chat_url3, chat_url4], [msg, chatbot])
616
+ msg.submit(respond, [msg, chatbot, chat_url1, chat_url2, chat_url3, chat_url4], [msg, chatbot])
617
+ clear.click(clear_chat, outputs=[msg, chatbot])
618
+
619
+ if __name__ == "__main__":
620
+ demo.launch(share=True)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio==4.32.0
2
+ requests==2.32.3
3
+ beautifulsoup4==4.12.3
4
+ python-dotenv==1.0.0