milwright commited on
Commit
b3f0e44
Β·
verified Β·
1 Parent(s): f26741d

Upload 3 files

Browse files
Files changed (2) hide show
  1. app.py +73 -53
  2. config.json +10 -10
app.py CHANGED
@@ -10,13 +10,13 @@ import urllib.parse
10
 
11
 
12
  # Configuration
13
- SPACE_NAME = "AI Assistant"
14
- SPACE_DESCRIPTION = "A customizable AI assistant"
15
 
16
  # Default configuration values
17
- DEFAULT_SYSTEM_PROMPT = """You are a research aid specializing in academic literature search and analysis. Your expertise spans discovering peer-reviewed sources, assessing research methodologies, synthesizing findings across studies, and delivering properly formatted citations. When responding, anchor claims in specific sources from provided URL contexts, differentiate between direct evidence and interpretive analysis, and note any limitations or contradictory results. Employ clear, accessible language that demystifies complex research, and propose connected research directions when appropriate. Your purpose is to serve as an informed research tool supporting users through initial concept development, exploratory investigation, information collection, and source compilation."""
18
- DEFAULT_TEMPERATURE = 0.7
19
- DEFAULT_MAX_TOKENS = 750
20
 
21
  # Try to load configuration from file (if modified by faculty)
22
  try:
@@ -33,16 +33,16 @@ except:
33
  max_tokens = DEFAULT_MAX_TOKENS
34
  print("ℹ️ Using default configuration")
35
 
36
- MODEL = "google/gemini-2.0-flash-001"
37
- THEME = "Default" # Gradio theme name
38
- GROUNDING_URLS = []
39
  # Get access code from environment variable for security
40
- # If SPACE_ACCESS_CODE is not set, no access control is applied
41
- ACCESS_CODE = os.environ.get("SPACE_ACCESS_CODE")
42
  ENABLE_DYNAMIC_URLS = True
43
 
44
  # Get API key from environment - customizable variable name with validation
45
- API_KEY = os.environ.get("OPENROUTER_API_KEY")
46
  if API_KEY:
47
  API_KEY = API_KEY.strip() # Remove any whitespace
48
  if not API_KEY: # Check if empty after stripping
@@ -53,21 +53,21 @@ def validate_api_key():
53
  """Validate API key configuration with detailed logging"""
54
  if not API_KEY:
55
  print(f"⚠️ API KEY CONFIGURATION ERROR:")
56
- print(f" Variable name: OPENROUTER_API_KEY")
57
  print(f" Status: Not set or empty")
58
- print(f" Action needed: Set 'OPENROUTER_API_KEY' in HuggingFace Space secrets")
59
  print(f" Expected format: sk-or-xxxxxxxxxx")
60
  return False
61
  elif not API_KEY.startswith('sk-or-'):
62
  print(f"⚠️ API KEY FORMAT WARNING:")
63
- print(f" Variable name: OPENROUTER_API_KEY")
64
  print(f" Current value: {API_KEY[:10]}..." if len(API_KEY) > 10 else API_KEY)
65
  print(f" Expected format: sk-or-xxxxxxxxxx")
66
  print(f" Note: OpenRouter keys should start with 'sk-or-'")
67
  return True # Still try to use it
68
  else:
69
  print(f"βœ… API Key configured successfully")
70
- print(f" Variable: OPENROUTER_API_KEY")
71
  print(f" Format: Valid OpenRouter key")
72
  return True
73
 
@@ -233,10 +233,10 @@ def generate_response(message, history):
233
  error_msg += f"Please configure your OpenRouter API key:\n"
234
  error_msg += f"1. Go to Settings (βš™οΈ) in your HuggingFace Space\n"
235
  error_msg += f"2. Click 'Variables and secrets'\n"
236
- error_msg += f"3. Add secret: **OPENROUTER_API_KEY**\n"
237
  error_msg += f"4. Value: Your OpenRouter API key (starts with `sk-or-`)\n\n"
238
  error_msg += f"Get your API key at: https://openrouter.ai/keys"
239
- print(f"❌ API request failed: No API key configured for OPENROUTER_API_KEY")
240
  return error_msg
241
 
242
  # Get grounding context
@@ -294,8 +294,8 @@ def generate_response(message, history):
294
  json={
295
  "model": MODEL,
296
  "messages": messages,
297
- "temperature": 0.7,
298
- "max_tokens": 750
299
  },
300
  timeout=30
301
  )
@@ -334,7 +334,7 @@ def generate_response(message, history):
334
  error_msg = f"πŸ” **Authentication Error**\n\n"
335
  error_msg += f"Your API key appears to be invalid or expired.\n\n"
336
  error_msg += f"**Troubleshooting:**\n"
337
- error_msg += f"1. Check that your **OPENROUTER_API_KEY** secret is set correctly\n"
338
  error_msg += f"2. Verify your API key at: https://openrouter.ai/keys\n"
339
  error_msg += f"3. Ensure your key starts with `sk-or-`\n"
340
  error_msg += f"4. Check that you have credits on your OpenRouter account"
@@ -483,22 +483,43 @@ def get_configuration_status():
483
  """Generate a configuration status message for display"""
484
  status_parts = []
485
 
486
- # API Key status - simplified
 
487
  if API_KEY_VALID:
488
  status_parts.append("βœ… **API Key:** Ready")
489
  else:
490
- status_parts.append("❌ **API Key:** Not configured ([set OPENROUTER_API_KEY in settings](https://huggingface.co/docs/hub/spaces-overview#managing-secrets))")
 
491
 
492
- # Basic info in a more compact format
493
- status_parts.append(f"**Model:** {MODEL.split('/')[-1]}") # Show only model name, not provider
 
 
 
 
494
 
495
- # Only show URLs if configured
496
  if GROUNDING_URLS:
497
- status_parts.append(f"**Context URLs:** {len(GROUNDING_URLS)} configured")
498
-
499
- # Access info only if restricted
 
 
 
 
 
 
500
  if ACCESS_CODE is not None:
501
- status_parts.append("πŸ” **Access:** Password protected")
 
 
 
 
 
 
 
 
 
502
 
503
  return "\n".join(status_parts)
504
 
@@ -528,16 +549,13 @@ with gr.Blocks(title=SPACE_NAME, theme=theme_class()) as demo:
528
  fn=store_and_generate_response, # Use wrapper function to store history
529
  title="", # Title already shown above
530
  description="", # Description already shown above
531
- examples=['Hello! How can you help me?', 'Tell me something interesting', 'What can you do?'],
532
  type="messages" # Use modern message format for better compatibility
533
  )
534
 
535
- # Export functionality - subtle placement
536
  with gr.Row():
537
- with gr.Column(scale=10):
538
- pass # Empty column for spacing
539
- with gr.Column(scale=2):
540
- export_btn = gr.Button("Export", variant="secondary", size="sm")
541
  export_file = gr.File(label="Download", visible=False)
542
 
543
  # Connect export functionality
@@ -546,8 +564,8 @@ with gr.Blocks(title=SPACE_NAME, theme=theme_class()) as demo:
546
  outputs=[export_file]
547
  )
548
 
549
- # Configuration status - minimized when everything is working
550
- with gr.Accordion("ℹ️ Status", open=not API_KEY_VALID):
551
  gr.Markdown(get_configuration_status())
552
 
553
  # Connect access verification
@@ -565,22 +583,24 @@ with gr.Blocks(title=SPACE_NAME, theme=theme_class()) as demo:
565
 
566
  # Faculty Configuration Section - appears at the bottom with password protection
567
  with gr.Accordion("πŸ”§ Faculty Configuration", open=False, visible=True) as faculty_section:
568
- gr.Markdown("**Faculty Only:** Edit assistant configuration. Requires FACULTY_CONFIG_PASSWORD secret.")
569
 
570
  # Check if faculty password is configured
571
- FACULTY_PASSWORD = os.environ.get("FACULTY_CONFIG_PASSWORD", "").strip()
572
 
573
  if FACULTY_PASSWORD:
574
  faculty_auth_state = gr.State(False)
575
 
576
  # Authentication row
577
- with gr.Row() as faculty_auth_row:
578
- faculty_password_input = gr.Textbox(
579
- label="Faculty Password",
580
- type="password",
581
- placeholder="Enter faculty configuration password"
582
- )
583
- faculty_auth_btn = gr.Button("Unlock Configuration", variant="primary")
 
 
584
  faculty_auth_status = gr.Markdown("")
585
 
586
  # Configuration editor (hidden until authenticated)
@@ -595,8 +615,8 @@ with gr.Blocks(title=SPACE_NAME, theme=theme_class()) as demo:
595
  except:
596
  current_config = {
597
  'system_prompt': SYSTEM_PROMPT,
598
- 'temperature': 0.7,
599
- 'max_tokens': 750,
600
  'locked': False
601
  }
602
 
@@ -612,14 +632,14 @@ with gr.Blocks(title=SPACE_NAME, theme=theme_class()) as demo:
612
  label="Temperature",
613
  minimum=0,
614
  maximum=2,
615
- value=current_config.get('temperature', 0.7),
616
  step=0.1
617
  )
618
  edit_max_tokens = gr.Slider(
619
  label="Max Tokens",
620
  minimum=50,
621
  maximum=4096,
622
- value=current_config.get('max_tokens', 750),
623
  step=50
624
  )
625
 
@@ -707,8 +727,8 @@ with gr.Blocks(title=SPACE_NAME, theme=theme_class()) as demo:
707
  return (
708
  "↩️ Reset to default values",
709
  gr.update(value=SYSTEM_PROMPT),
710
- gr.update(value=0.7),
711
- gr.update(value=750)
712
  )
713
 
714
  # Connect authentication
@@ -737,7 +757,7 @@ with gr.Blocks(title=SPACE_NAME, theme=theme_class()) as demo:
737
  outputs=[config_status, edit_system_prompt, edit_temperature, edit_max_tokens]
738
  )
739
  else:
740
- gr.Markdown("ℹ️ Faculty configuration is not enabled. Set FACULTY_CONFIG_PASSWORD in Space secrets to enable.")
741
 
742
  if __name__ == "__main__":
743
  demo.launch()
 
10
 
11
 
12
  # Configuration
13
+ SPACE_NAME = "Math-o-Matic"
14
+ SPACE_DESCRIPTION = "A customizable AI assistant for advanced mathematics help and numeracy guidance"
15
 
16
  # Default configuration values
17
+ DEFAULT_SYSTEM_PROMPT = """You are an AI assistant specialized in mathematics and statistics who guides users through problem-solving rather than providing direct answers. You help users discover solutions by asking strategic questions ('What do we know so far?' 'What method might apply here?' 'Can you identify a pattern?'), prompting them to explain their reasoning, and offering hints that build on their current understanding. Format all mathematical expressions in LaTeX (inline: $x^2 + y^2 = r^2$, display: $$\int_a^b f(x)dx$$). When users are stuck, provide scaffolded support: suggest examining simpler cases, identifying relevant formulas or theorems, or breaking the problem into smaller parts. Use multiple representations to illuminate different aspects of the problem, validate partial progress to build confidence, and help users recognize and correct their own errors through targeted questions rather than corrections. Your goal is to develop problem-solving skills and mathematical reasoning, not just arrive at answers."""
18
+ DEFAULT_TEMPERATURE = 0.6
19
+ DEFAULT_MAX_TOKENS = 1000
20
 
21
  # Try to load configuration from file (if modified by faculty)
22
  try:
 
33
  max_tokens = DEFAULT_MAX_TOKENS
34
  print("ℹ️ Using default configuration")
35
 
36
+ MODEL = "anthropic/claude-3.5-sonnet"
37
+ THEME = "Glass" # Gradio theme name
38
+ GROUNDING_URLS = ["https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/MathMode.html", "https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/TeXEntities.html", "https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Matrices.html", "https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/StdFuncts.html"]
39
  # Get access code from environment variable for security
40
+ # If ACCESS_CODE is not set, no access control is applied
41
+ ACCESS_CODE = os.environ.get("ACCESS_CODE")
42
  ENABLE_DYNAMIC_URLS = True
43
 
44
  # Get API key from environment - customizable variable name with validation
45
+ API_KEY = os.environ.get("API_KEY")
46
  if API_KEY:
47
  API_KEY = API_KEY.strip() # Remove any whitespace
48
  if not API_KEY: # Check if empty after stripping
 
53
  """Validate API key configuration with detailed logging"""
54
  if not API_KEY:
55
  print(f"⚠️ API KEY CONFIGURATION ERROR:")
56
+ print(f" Variable name: API_KEY")
57
  print(f" Status: Not set or empty")
58
+ print(f" Action needed: Set 'API_KEY' in HuggingFace Space secrets")
59
  print(f" Expected format: sk-or-xxxxxxxxxx")
60
  return False
61
  elif not API_KEY.startswith('sk-or-'):
62
  print(f"⚠️ API KEY FORMAT WARNING:")
63
+ print(f" Variable name: API_KEY")
64
  print(f" Current value: {API_KEY[:10]}..." if len(API_KEY) > 10 else API_KEY)
65
  print(f" Expected format: sk-or-xxxxxxxxxx")
66
  print(f" Note: OpenRouter keys should start with 'sk-or-'")
67
  return True # Still try to use it
68
  else:
69
  print(f"βœ… API Key configured successfully")
70
+ print(f" Variable: API_KEY")
71
  print(f" Format: Valid OpenRouter key")
72
  return True
73
 
 
233
  error_msg += f"Please configure your OpenRouter API key:\n"
234
  error_msg += f"1. Go to Settings (βš™οΈ) in your HuggingFace Space\n"
235
  error_msg += f"2. Click 'Variables and secrets'\n"
236
+ error_msg += f"3. Add secret: **API_KEY**\n"
237
  error_msg += f"4. Value: Your OpenRouter API key (starts with `sk-or-`)\n\n"
238
  error_msg += f"Get your API key at: https://openrouter.ai/keys"
239
+ print(f"❌ API request failed: No API key configured for API_KEY")
240
  return error_msg
241
 
242
  # Get grounding context
 
294
  json={
295
  "model": MODEL,
296
  "messages": messages,
297
+ "temperature": 0.6,
298
+ "max_tokens": 1000
299
  },
300
  timeout=30
301
  )
 
334
  error_msg = f"πŸ” **Authentication Error**\n\n"
335
  error_msg += f"Your API key appears to be invalid or expired.\n\n"
336
  error_msg += f"**Troubleshooting:**\n"
337
+ error_msg += f"1. Check that your **API_KEY** secret is set correctly\n"
338
  error_msg += f"2. Verify your API key at: https://openrouter.ai/keys\n"
339
  error_msg += f"3. Ensure your key starts with `sk-or-`\n"
340
  error_msg += f"4. Check that you have credits on your OpenRouter account"
 
483
  """Generate a configuration status message for display"""
484
  status_parts = []
485
 
486
+ # API Key status
487
+ status_parts.append("### πŸ”‘ API Configuration")
488
  if API_KEY_VALID:
489
  status_parts.append("βœ… **API Key:** Ready")
490
  else:
491
+ status_parts.append("❌ **API Key:** Not configured")
492
+ status_parts.append(" Set `API_KEY` in Space secrets")
493
 
494
+ # Model and parameters
495
+ status_parts.append("") # Blank line
496
+ status_parts.append("### πŸ€– Model Settings")
497
+ status_parts.append(f"**Model:** {MODEL.split('/')[-1]}")
498
+ status_parts.append(f"**Temperature:** 0.6")
499
+ status_parts.append(f"**Max Tokens:** 1000")
500
 
501
+ # URL Context if configured
502
  if GROUNDING_URLS:
503
+ status_parts.append("") # Blank line
504
+ status_parts.append("### πŸ”— Context Sources")
505
+ status_parts.append(f"**URLs Configured:** {len(GROUNDING_URLS)}")
506
+ for i, url in enumerate(GROUNDING_URLS[:2], 1):
507
+ status_parts.append(f" {i}. {url[:50]}{'...' if len(url) > 50 else ''}")
508
+ if len(GROUNDING_URLS) > 2:
509
+ status_parts.append(f" ... and {len(GROUNDING_URLS) - 2} more")
510
+
511
+ # Access control
512
  if ACCESS_CODE is not None:
513
+ status_parts.append("") # Blank line
514
+ status_parts.append("### πŸ” Access Control")
515
+ status_parts.append("**Status:** Password protected")
516
+
517
+ # System prompt
518
+ status_parts.append("") # Blank line
519
+ status_parts.append("### πŸ“ System Prompt")
520
+ # Show first 200 chars of system prompt
521
+ prompt_preview = SYSTEM_PROMPT[:200] + "..." if len(SYSTEM_PROMPT) > 200 else SYSTEM_PROMPT
522
+ status_parts.append(f"```\n{prompt_preview}\n```")
523
 
524
  return "\n".join(status_parts)
525
 
 
549
  fn=store_and_generate_response, # Use wrapper function to store history
550
  title="", # Title already shown above
551
  description="", # Description already shown above
552
+ examples=['Can you help me with the quadratic formula?', 'What is Bayesian statistics?', 'Help me work with a math problem'],
553
  type="messages" # Use modern message format for better compatibility
554
  )
555
 
556
+ # Export functionality
557
  with gr.Row():
558
+ export_btn = gr.Button("πŸ“₯ Export Conversation", variant="secondary", size="sm")
 
 
 
559
  export_file = gr.File(label="Download", visible=False)
560
 
561
  # Connect export functionality
 
564
  outputs=[export_file]
565
  )
566
 
567
+ # Configuration status
568
+ with gr.Accordion("πŸ“Š Configuration Status", open=True):
569
  gr.Markdown(get_configuration_status())
570
 
571
  # Connect access verification
 
583
 
584
  # Faculty Configuration Section - appears at the bottom with password protection
585
  with gr.Accordion("πŸ”§ Faculty Configuration", open=False, visible=True) as faculty_section:
586
+ gr.Markdown("**Faculty Only:** Edit assistant configuration. Requires CONFIG_CODE secret.")
587
 
588
  # Check if faculty password is configured
589
+ FACULTY_PASSWORD = os.environ.get("CONFIG_CODE", "").strip()
590
 
591
  if FACULTY_PASSWORD:
592
  faculty_auth_state = gr.State(False)
593
 
594
  # Authentication row
595
+ with gr.Column() as faculty_auth_row:
596
+ with gr.Row():
597
+ faculty_password_input = gr.Textbox(
598
+ label="Faculty Password",
599
+ type="password",
600
+ placeholder="Enter faculty configuration password",
601
+ scale=3
602
+ )
603
+ faculty_auth_btn = gr.Button("Unlock Configuration", variant="primary", scale=1)
604
  faculty_auth_status = gr.Markdown("")
605
 
606
  # Configuration editor (hidden until authenticated)
 
615
  except:
616
  current_config = {
617
  'system_prompt': SYSTEM_PROMPT,
618
+ 'temperature': 0.6,
619
+ 'max_tokens': 1000,
620
  'locked': False
621
  }
622
 
 
632
  label="Temperature",
633
  minimum=0,
634
  maximum=2,
635
+ value=current_config.get('temperature', 0.6),
636
  step=0.1
637
  )
638
  edit_max_tokens = gr.Slider(
639
  label="Max Tokens",
640
  minimum=50,
641
  maximum=4096,
642
+ value=current_config.get('max_tokens', 1000),
643
  step=50
644
  )
645
 
 
727
  return (
728
  "↩️ Reset to default values",
729
  gr.update(value=SYSTEM_PROMPT),
730
+ gr.update(value=0.6),
731
+ gr.update(value=1000)
732
  )
733
 
734
  # Connect authentication
 
757
  outputs=[config_status, edit_system_prompt, edit_temperature, edit_max_tokens]
758
  )
759
  else:
760
+ gr.Markdown("ℹ️ Faculty configuration is not enabled. Set CONFIG_CODE in Space secrets to enable.")
761
 
762
  if __name__ == "__main__":
763
  demo.launch()
config.json CHANGED
@@ -1,13 +1,13 @@
1
  {
2
- "name": "AI Assistant",
3
- "description": "A customizable AI assistant",
4
- "system_prompt": "You are a research aid specializing in academic literature search and analysis. Your expertise spans discovering peer-reviewed sources, assessing research methodologies, synthesizing findings across studies, and delivering properly formatted citations. When responding, anchor claims in specific sources from provided URL contexts, differentiate between direct evidence and interpretive analysis, and note any limitations or contradictory results. Employ clear, accessible language that demystifies complex research, and propose connected research directions when appropriate. Your purpose is to serve as an informed research tool supporting users through initial concept development, exploratory investigation, information collection, and source compilation.",
5
- "model": "google/gemini-2.0-flash-001",
6
- "api_key_var": "OPENROUTER_API_KEY",
7
- "temperature": 0.7,
8
- "max_tokens": 750,
9
- "examples": "['Hello! How can you help me?', 'Tell me something interesting', 'What can you do?']",
10
- "grounding_urls": "[]",
11
  "enable_dynamic_urls": true,
12
- "theme": "Default"
13
  }
 
1
  {
2
+ "name": "Math-o-Matic",
3
+ "description": "A customizable AI assistant for advanced mathematics help and numeracy guidance",
4
+ "system_prompt": "You are an AI assistant specialized in mathematics and statistics who guides users through problem-solving rather than providing direct answers. You help users discover solutions by asking strategic questions ('What do we know so far?' 'What method might apply here?' 'Can you identify a pattern?'), prompting them to explain their reasoning, and offering hints that build on their current understanding. Format all mathematical expressions in LaTeX (inline: $x^2 + y^2 = r^2$, display: $$\\int_a^b f(x)dx$$). When users are stuck, provide scaffolded support: suggest examining simpler cases, identifying relevant formulas or theorems, or breaking the problem into smaller parts. Use multiple representations to illuminate different aspects of the problem, validate partial progress to build confidence, and help users recognize and correct their own errors through targeted questions rather than corrections. Your goal is to develop problem-solving skills and mathematical reasoning, not just arrive at answers.",
5
+ "model": "anthropic/claude-3.5-sonnet",
6
+ "api_key_var": "API_KEY",
7
+ "temperature": 0.6,
8
+ "max_tokens": 1000,
9
+ "examples": "['Can you help me with the quadratic formula?', 'What is Bayesian statistics?', 'Help me work with a math problem']",
10
+ "grounding_urls": "[\"https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/MathMode.html\", \"https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/TeXEntities.html\", \"https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/Matrices.html\", \"https://www.maths.tcd.ie/~dwilkins/LaTeXPrimer/StdFuncts.html\"]",
11
  "enable_dynamic_urls": true,
12
+ "theme": "Glass"
13
  }