milwright commited on
Commit
814e035
·
1 Parent(s): 4fde71b

Remove RAG functionality and enhance template system

Browse files

- Add enhanced template system with Research and Socratic templates
- Remove all RAG/vector search functionality and dependencies
- Clean up requirements.txt to remove RAG-related packages
- Update documentation to remove RAG references
- Maintain core functionality: URL grounding, dynamic URL fetching, template system
- Fix preview functionality and export features
- Update support documentation

Files changed (4) hide show
  1. README.md +4 -6
  2. app.py +143 -258
  3. requirements.txt +1 -8
  4. support_docs.py +6 -13
README.md CHANGED
@@ -14,14 +14,14 @@ short_description: Configure, download, and deploy a simple chat interface
14
 
15
  # Chat UI Helper
16
 
17
- A Gradio-based tool for generating and configuring chat interfaces for HuggingFace Spaces. Create deployable packages with custom assistants, web scraping capabilities, and optional vector RAG functionality.
18
 
19
  ## Features
20
 
21
  ### Spaces Configuration
22
  - **Custom Assistant Creation**: Define role, purpose, audience, and tasks
23
- - **Template System**: Choose from research assistant template or build from scratch
24
- - **Tool Integration**: Optional dynamic URL fetching and document RAG
25
  - **Access Control**: Secure access code protection for educational use
26
  - **Complete Deployment Package**: Generates app.py, requirements.txt, README.md, and config.json
27
 
@@ -48,14 +48,12 @@ Set your OpenRouter API key as a secret:
48
  Each generated space includes:
49
  - **OpenRouter API Integration**: Support for multiple LLM models
50
  - **Web Scraping**: Simple HTTP requests with BeautifulSoup for URL content fetching
51
- - **Document RAG**: Optional upload and search through PDF, DOCX, TXT, MD files
52
  - **Access Control**: Environment-based student access codes
53
  - **Modern UI**: Gradio 5.x ChatInterface with proper message formatting
54
 
55
  ## Architecture
56
 
57
- - **Main Application**: `app.py` with two-tab interface
58
- - **Document Processing**: RAG pipeline with FAISS vector search
59
  - **Web Scraping**: HTTP requests with BeautifulSoup for content extraction
60
  - **Template Generation**: Complete HuggingFace Space creation
61
 
 
14
 
15
  # Chat UI Helper
16
 
17
+ A Gradio-based tool for generating and configuring chat interfaces for HuggingFace Spaces. Create deployable packages with custom assistants and web scraping capabilities.
18
 
19
  ## Features
20
 
21
  ### Spaces Configuration
22
  - **Custom Assistant Creation**: Define role, purpose, audience, and tasks
23
+ - **Template System**: Choose from research assistant template or build from scratch
24
+ - **Tool Integration**: Optional dynamic URL fetching
25
  - **Access Control**: Secure access code protection for educational use
26
  - **Complete Deployment Package**: Generates app.py, requirements.txt, README.md, and config.json
27
 
 
48
  Each generated space includes:
49
  - **OpenRouter API Integration**: Support for multiple LLM models
50
  - **Web Scraping**: Simple HTTP requests with BeautifulSoup for URL content fetching
 
51
  - **Access Control**: Environment-based student access codes
52
  - **Modern UI**: Gradio 5.x ChatInterface with proper message formatting
53
 
54
  ## Architecture
55
 
56
+ - **Main Application**: `app.py` with three-tab interface
 
57
  - **Web Scraping**: HTTP requests with BeautifulSoup for content extraction
58
  - **Template Generation**: Complete HuggingFace Space creation
59
 
app.py CHANGED
@@ -39,13 +39,7 @@ def get_grounding_context_simple(urls):
39
  return "\n\n" + "\n\n".join(context_parts) + "\n\n"
40
  return ""
41
 
42
- # Import RAG components
43
- try:
44
- from rag_tool import RAGTool
45
- HAS_RAG = True
46
- except ImportError:
47
- HAS_RAG = False
48
- RAGTool = None
49
 
50
  # Load environment variables from .env file
51
  load_dotenv()
@@ -152,8 +146,7 @@ GROUNDING_URLS = {grounding_urls}
152
  # Get access code from environment variable for security
153
  ACCESS_CODE = os.environ.get("SPACE_ACCESS_CODE", "{access_code}")
154
  ENABLE_DYNAMIC_URLS = {enable_dynamic_urls}
155
- ENABLE_VECTOR_RAG = {enable_vector_rag}
156
- RAG_DATA = {rag_data_json}
157
 
158
  # Get API key from environment - customizable variable name with validation
159
  API_KEY = os.environ.get("{api_key_var}")
@@ -309,10 +302,31 @@ def export_conversation_to_markdown(conversation_history):
309
  markdown_content = f"""# Conversation Export
310
  Generated on: {{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}}
311
 
312
- ---
313
 
 
 
 
 
 
 
314
  """
315
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316
  message_pair_count = 0
317
  for i, message in enumerate(conversation_history):
318
  if isinstance(message, dict):
@@ -335,35 +349,7 @@ Generated on: {{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}}
335
 
336
  return markdown_content
337
 
338
- # Initialize RAG context if enabled
339
- if ENABLE_VECTOR_RAG and RAG_DATA:
340
- try:
341
- import faiss
342
- import numpy as np
343
- import base64
344
-
345
- class SimpleRAGContext:
346
- def __init__(self, rag_data):
347
- # Deserialize FAISS index
348
- index_bytes = base64.b64decode(rag_data['index_base64'])
349
- self.index = faiss.deserialize_index(index_bytes)
350
-
351
- # Restore chunks and mappings
352
- self.chunks = rag_data['chunks']
353
- self.chunk_ids = rag_data['chunk_ids']
354
-
355
- def get_context(self, query, max_chunks=3):
356
- """Get relevant context - simplified version"""
357
- # In production, you'd compute query embedding here
358
- # For now, return a simple message
359
- return "\\n\\n[RAG context would be retrieved here based on similarity search]\\n\\n"
360
-
361
- rag_context_provider = SimpleRAGContext(RAG_DATA)
362
- except Exception as e:
363
- print(f"Failed to initialize RAG: {{e}}")
364
- rag_context_provider = None
365
- else:
366
- rag_context_provider = None
367
 
368
  def generate_response(message, history):
369
  """Generate response using OpenRouter API"""
@@ -383,11 +369,7 @@ def generate_response(message, history):
383
  # Get grounding context
384
  grounding_context = get_grounding_context()
385
 
386
- # Add RAG context if available
387
- if ENABLE_VECTOR_RAG and rag_context_provider:
388
- rag_context = rag_context_provider.get_context(message)
389
- if rag_context:
390
- grounding_context += rag_context
391
 
392
  # If dynamic URLs are enabled, check message for URLs to fetch
393
  if ENABLE_DYNAMIC_URLS:
@@ -643,9 +625,6 @@ def get_configuration_status():
643
 
644
  if ENABLE_DYNAMIC_URLS:
645
  status_parts.append("🔄 **Dynamic URLs:** Enabled")
646
-
647
- if ENABLE_VECTOR_RAG:
648
- status_parts.append("📚 **Document RAG:** Enabled")
649
 
650
  if ACCESS_CODE:
651
  status_parts.append("🔐 **Access Control:** Enabled")
@@ -861,18 +840,11 @@ Generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} with Chat U/I Helper
861
 
862
  return readme_content
863
 
864
- def create_requirements(enable_vector_rag=False):
865
  """Generate requirements.txt"""
866
- base_requirements = "gradio>=4.44.1\nrequests>=2.32.3\nbeautifulsoup4>=4.12.3\npython-dotenv>=1.0.0"
867
-
868
-
869
- if enable_vector_rag:
870
- base_requirements += "\n\n# Vector RAG dependencies"
871
- base_requirements += "\nfaiss-cpu>=1.11.0\nnumpy>=1.25.0,<3.0\nsentence-transformers>=2.2.2\nPyMuPDF>=1.23.0\npython-docx>=0.8.11"
872
-
873
- return base_requirements
874
 
875
- def generate_zip(name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, access_code="", enable_dynamic_urls=False, url1="", url2="", url3="", url4="", enable_vector_rag=False, rag_data=None):
876
  """Generate deployable zip file"""
877
 
878
  # Process examples
@@ -906,9 +878,7 @@ def generate_zip(name, description, system_prompt, model, api_key_var, temperatu
906
  'examples': examples_json,
907
  'grounding_urls': json.dumps(grounding_urls),
908
  'access_code': "", # Access code stored in environment variable for security
909
- 'enable_dynamic_urls': enable_dynamic_urls,
910
- 'enable_vector_rag': enable_vector_rag,
911
- 'rag_data_json': json.dumps(rag_data) if rag_data else 'None'
912
  }
913
 
914
  # Generate files
@@ -917,7 +887,7 @@ def generate_zip(name, description, system_prompt, model, api_key_var, temperatu
917
  readme_config = config.copy()
918
  readme_config['access_code'] = access_code or ""
919
  readme_content = create_readme(readme_config)
920
- requirements_content = create_requirements(enable_vector_rag)
921
 
922
  # Create zip file with clean naming
923
  filename = f"{name.lower().replace(' ', '_').replace('-', '_')}.zip"
@@ -938,93 +908,7 @@ def generate_zip(name, description, system_prompt, model, api_key_var, temperatu
938
  return filename
939
 
940
  # Define callback functions outside the interface
941
- def toggle_rag_section(enable_rag):
942
- """Toggle visibility of RAG section"""
943
- return gr.update(visible=enable_rag)
944
-
945
- def process_documents(files, current_rag_tool):
946
- """Process uploaded documents"""
947
- if not files:
948
- return "Please upload files first", current_rag_tool
949
-
950
- if not HAS_RAG:
951
- return "RAG functionality not available. Please install required dependencies.", current_rag_tool
952
-
953
- try:
954
- # Check file paths are valid
955
- file_paths = []
956
- for file in files:
957
- if hasattr(file, 'name'):
958
- file_paths.append(file.name)
959
- else:
960
- file_paths.append(str(file))
961
-
962
- print(f"Processing {len(file_paths)} files for RAG...")
963
-
964
- # Initialize RAG tool if not exists
965
- if not current_rag_tool and RAGTool is not None:
966
- print("Initializing RAG tool...")
967
- current_rag_tool = RAGTool()
968
-
969
- # Process files with progress feedback
970
- print("Processing documents and creating embeddings...")
971
- result = current_rag_tool.process_uploaded_files(file_paths)
972
-
973
- if result['success']:
974
- # Create status message
975
- status_parts = [f"✅ {result['message']}"]
976
-
977
- # Add file summary
978
- if result['summary']['files_processed']:
979
- status_parts.append("\n**Processed files:**")
980
- for file_info in result['summary']['files_processed']:
981
- status_parts.append(f"- {file_info['name']} ({file_info['chunks']} chunks)")
982
-
983
- # Add errors if any
984
- if result.get('errors'):
985
- status_parts.append("\n**Errors:**")
986
- for error in result['errors']:
987
- status_parts.append(f"- {error['file']}: {error['error']}")
988
-
989
- # Add index stats
990
- if result.get('index_stats'):
991
- stats = result['index_stats']
992
- status_parts.append(f"\n**Index stats:** {stats['total_chunks']} chunks, {stats['dimension']}D embeddings")
993
-
994
- return "\n".join(status_parts), current_rag_tool
995
- else:
996
- return f"❌ {result['message']}", current_rag_tool
997
-
998
- except ImportError as e:
999
- error_msg = f"❌ Missing dependencies: {str(e)}\n\n"
1000
- error_msg += "To use RAG functionality, install:\n"
1001
- error_msg += "- sentence-transformers>=2.2.2\n"
1002
- error_msg += "- faiss-cpu==1.7.4\n"
1003
- error_msg += "- PyMuPDF>=1.23.0 (for PDF files)\n"
1004
- error_msg += "- python-docx>=0.8.11 (for DOCX files)"
1005
- return error_msg, current_rag_tool
1006
- except RuntimeError as e:
1007
- error_msg = f"❌ Model initialization error: {str(e)}\n\n"
1008
- if "network" in str(e).lower() or "download" in str(e).lower():
1009
- error_msg += "This appears to be a network issue. Please:\n"
1010
- error_msg += "1. Check your internet connection\n"
1011
- error_msg += "2. Try again in a few moments\n"
1012
- error_msg += "3. If the problem persists, restart the application"
1013
- elif "memory" in str(e).lower():
1014
- error_msg += "This appears to be a memory issue. Please:\n"
1015
- error_msg += "1. Try uploading smaller documents\n"
1016
- error_msg += "2. Process documents one at a time\n"
1017
- error_msg += "3. Restart the application if needed"
1018
- return error_msg, current_rag_tool
1019
- except Exception as e:
1020
- error_msg = f"❌ Unexpected error processing documents: {str(e)}\n\n"
1021
- error_msg += "This may be due to:\n"
1022
- error_msg += "- Large files causing memory issues\n"
1023
- error_msg += "- Network problems downloading the embedding model\n"
1024
- error_msg += "- File format issues\n\n"
1025
- error_msg += "Try: uploading smaller files, checking your internet connection, or restarting the application."
1026
- print(f"RAG processing error: {e}")
1027
- return error_msg, current_rag_tool
1028
 
1029
  def update_sandbox_preview(config_data):
1030
  """Update the sandbox preview with generated content"""
@@ -1038,7 +922,7 @@ def update_sandbox_preview(config_data):
1038
  - **Temperature:** {config_data.get('temperature', 'N/A')}
1039
  - **Max Tokens:** {config_data.get('max_tokens', 'N/A')}
1040
  - **Dynamic URLs:** {'✅ Enabled' if config_data.get('enable_dynamic_urls') else '❌ Disabled'}
1041
- - **Vector RAG:** {'✅ Enabled' if config_data.get('enable_vector_rag') else '❌ Disabled'}
1042
 
1043
  **System Prompt Preview:**
1044
  ```
@@ -1073,14 +957,21 @@ def update_sandbox_preview(config_data):
1073
 
1074
  return preview_text, preview_html
1075
 
1076
- def on_preview_combined(name, description, system_prompt, model, temperature, max_tokens, examples_text, enable_dynamic_urls, enable_vector_rag, rag_tool_state, url1="", url2="", url3="", url4=""):
1077
  """Generate configuration and return preview updates"""
1078
  if not name or not name.strip():
1079
  return (
1080
  {},
1081
  gr.update(value="**Error:** Please provide a Space Title to preview", visible=True),
1082
  gr.update(visible=False),
1083
- gr.update(value="Configuration will appear here after preview generation.")
 
 
 
 
 
 
 
1084
  )
1085
 
1086
  try:
@@ -1090,7 +981,14 @@ def on_preview_combined(name, description, system_prompt, model, temperature, ma
1090
  {},
1091
  gr.update(value="**Error:** Please provide a System Prompt for the assistant", visible=True),
1092
  gr.update(visible=False),
1093
- gr.update(value="Configuration will appear here after preview generation.")
 
 
 
 
 
 
 
1094
  )
1095
 
1096
  final_system_prompt = system_prompt.strip()
@@ -1108,8 +1006,6 @@ def on_preview_combined(name, description, system_prompt, model, temperature, ma
1108
  'url2': url2,
1109
  'url3': url3,
1110
  'url4': url4,
1111
- 'enable_vector_rag': enable_vector_rag,
1112
- 'rag_tool_state': rag_tool_state,
1113
  'examples_text': examples_text,
1114
  'preview_ready': True
1115
  }
@@ -1119,9 +1015,7 @@ def on_preview_combined(name, description, system_prompt, model, temperature, ma
1119
  > *{final_system_prompt[:600]}{'...' if len(final_system_prompt) > 600 else '...'}*
1120
 
1121
  Tip: Try different configurations of your space before generating the deployment package."""
1122
- config_display = f"""### Current Configuration
1123
-
1124
- > **Configuration**:
1125
  - **Name:** {name}
1126
  - **Description:** {description or 'No description provided'}
1127
  - **Model:** {model}
@@ -1140,11 +1034,42 @@ Tip: Try different configurations of your space before generating the deployment
1140
  # Show success notification
1141
  gr.Info(f"✅ Preview generated successfully for '{name}'! Switch to Preview tab.")
1142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1143
  return (
1144
  config_data,
1145
  gr.update(value=preview_text, visible=True),
1146
  gr.update(visible=True),
1147
- gr.update(value=config_display)
 
 
 
 
 
 
 
1148
  )
1149
 
1150
  except Exception as e:
@@ -1152,7 +1077,14 @@ Tip: Try different configurations of your space before generating the deployment
1152
  {},
1153
  gr.update(value=f"**Error:** {str(e)}", visible=True),
1154
  gr.update(visible=False),
1155
- gr.update(value="Configuration will appear here after preview generation.")
 
 
 
 
 
 
 
1156
  )
1157
 
1158
  def update_preview_display(config_data):
@@ -1173,7 +1105,7 @@ Your assistant "{config_data['name']}" is configured and ready to test.
1173
  - **Temperature:** {config_data['temperature']}
1174
  - **Max Tokens:** {config_data['max_tokens']}
1175
  - **Dynamic URLs:** {'✅ Enabled' if config_data['enable_dynamic_urls'] else '❌ Disabled'}
1176
- - **Vector RAG:** {'✅ Enabled' if config_data['enable_vector_rag'] else '❌ Disabled'}
1177
 
1178
  **System Prompt:**
1179
  {config_data['system_prompt'][:600]}{'...' if len(config_data['system_prompt']) > 600 else ''}
@@ -1193,7 +1125,7 @@ Use the chat interface below to test your assistant before generating the deploy
1193
 
1194
  **Features:**
1195
  - **Dynamic URL Fetching:** {'✅ Enabled' if config_data['enable_dynamic_urls'] else '❌ Disabled'}
1196
- - **Document RAG:** {'✅ Enabled' if config_data['enable_vector_rag'] else '❌ Disabled'}
1197
 
1198
  **System Prompt:**
1199
  ```
@@ -1253,20 +1185,7 @@ Once you set your API key, you'll be able to test real conversations in this pre
1253
  grounding_urls = config_urls if any(url for url in config_urls if url) else [url1, url2, url3, url4]
1254
  grounding_context = get_cached_grounding_context([url for url in grounding_urls if url and url.strip()])
1255
 
1256
- # Add RAG context if available (actual retrieval for preview)
1257
- rag_context = ""
1258
- if config_data.get('enable_vector_rag') and HAS_RAG:
1259
- try:
1260
- # Get RAG tool from config_data if available
1261
- rag_tool_state = config_data.get('rag_tool_state')
1262
- if rag_tool_state:
1263
- rag_context = rag_tool_state.get_relevant_context(message, max_chunks=2)
1264
- if rag_context:
1265
- rag_context = f"\n\n**RAG Context (Preview):**\n{rag_context}\n\n"
1266
- else:
1267
- rag_context = "\n\n[RAG: No processed documents available for context]\n\n"
1268
- except Exception as e:
1269
- rag_context = f"\n\n[RAG context error: {str(e)}]\n\n"
1270
 
1271
  # If dynamic URLs are enabled, check message for URLs to fetch
1272
  dynamic_context = ""
@@ -1281,7 +1200,7 @@ Once you set your API key, you'll be able to test real conversations in this pre
1281
  dynamic_context = "\n".join(dynamic_context_parts)
1282
 
1283
  # Build enhanced system prompt with all contexts
1284
- enhanced_system_prompt = config_data.get('system_prompt', '') + grounding_context + rag_context + dynamic_context
1285
 
1286
  # Build messages array for the API
1287
  messages = [{"role": "system", "content": enhanced_system_prompt}]
@@ -1360,12 +1279,12 @@ def clear_preview_chat():
1360
  """Clear preview chat"""
1361
  return "", []
1362
 
1363
- def export_preview_conversation(history):
1364
  """Export preview conversation to markdown"""
1365
  if not history:
1366
  return gr.update(visible=False)
1367
 
1368
- markdown_content = export_conversation_to_markdown(history)
1369
 
1370
  # Save to temporary file
1371
  import tempfile
@@ -1375,24 +1294,19 @@ def export_preview_conversation(history):
1375
 
1376
  return gr.update(value=temp_file, visible=True)
1377
 
1378
- def on_generate(name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, access_code, enable_dynamic_urls, url1, url2, url3, url4, enable_vector_rag, rag_tool_state):
1379
  if not name or not name.strip():
1380
  return gr.update(value="Error: Please provide a Space Title", visible=True), gr.update(visible=False), {}
1381
 
1382
 
1383
  try:
1384
- # Get RAG data if enabled
1385
- rag_data = None
1386
- if enable_vector_rag and rag_tool_state:
1387
- rag_data = rag_tool_state.get_serialized_data()
1388
-
1389
  # Use the system prompt directly (template selector already updates it)
1390
  if not system_prompt or not system_prompt.strip():
1391
  return gr.update(value="Error: Please provide a System Prompt for the assistant", visible=True), gr.update(visible=False), {}
1392
 
1393
  final_system_prompt = system_prompt.strip()
1394
 
1395
- filename = generate_zip(name, description, final_system_prompt, model, api_key_var, temperature, max_tokens, examples_text, access_code, enable_dynamic_urls, url1, url2, url3, url4, enable_vector_rag, rag_data)
1396
 
1397
  success_msg = f"""**Deployment package ready!**
1398
 
@@ -1420,7 +1334,6 @@ def on_generate(name, description, system_prompt, model, api_key_var, temperatur
1420
  'temperature': temperature,
1421
  'max_tokens': max_tokens,
1422
  'enable_dynamic_urls': enable_dynamic_urls,
1423
- 'enable_vector_rag': enable_vector_rag,
1424
  'filename': filename
1425
  }
1426
 
@@ -1834,63 +1747,8 @@ with gr.Blocks(
1834
 
1835
 
1836
 
1837
- # Document RAG section
1838
- enable_vector_rag = gr.Checkbox(
1839
- label="Enable Document RAG",
1840
- value=False,
1841
- info="Upload documents for context-aware responses (PDF, DOCX, TXT, MD)",
1842
- visible=HAS_RAG
1843
- )
1844
 
1845
- with gr.Column(visible=False) as rag_section:
1846
- gr.Markdown("### Document Upload")
1847
- file_upload = gr.File(
1848
- label="Upload Documents",
1849
- file_types=[".pdf", ".docx", ".txt", ".md"],
1850
- file_count="multiple"
1851
- )
1852
- process_btn = gr.Button("Process Documents", variant="secondary")
1853
- rag_status = gr.Markdown()
1854
-
1855
- # State to store RAG tool
1856
- rag_tool_state = gr.State(None)
1857
-
1858
- with gr.Accordion("URL Grounding (Optional)", open=True):
1859
- gr.Markdown("Add URLs to provide context. Content will be fetched and added to the system prompt.")
1860
-
1861
- # Initial URL fields
1862
- url1 = gr.Textbox(
1863
- label="URL 1",
1864
- placeholder="https://example.com/page1",
1865
- info="First URL for context grounding"
1866
- )
1867
-
1868
- url2 = gr.Textbox(
1869
- label="URL 2",
1870
- placeholder="https://example.com/page2",
1871
- info="Second URL for context grounding"
1872
- )
1873
-
1874
- # Additional URL fields (initially hidden)
1875
- url3 = gr.Textbox(
1876
- label="URL 3",
1877
- placeholder="https://example.com/page3",
1878
- info="Third URL for context grounding",
1879
- visible=False
1880
- )
1881
-
1882
- url4 = gr.Textbox(
1883
- label="URL 4",
1884
- placeholder="https://example.com/page4",
1885
- info="Fourth URL for context grounding",
1886
- visible=False
1887
- )
1888
-
1889
- # URL management buttons
1890
- with gr.Row():
1891
- add_url_btn = gr.Button("+ Add URLs", size="sm")
1892
- remove_url_btn = gr.Button("- Remove URLs", size="sm", visible=False)
1893
- url_count = gr.State(2) # Track number of visible URLs
1894
 
1895
  examples_text = gr.Textbox(
1896
  label="Example Prompts (one per line)",
@@ -1925,6 +1783,44 @@ with gr.Blocks(
1925
  value=1500,
1926
  step=50
1927
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1928
 
1929
  with gr.Row():
1930
  preview_btn = gr.Button("Preview Deployment Package", variant="secondary")
@@ -1960,24 +1856,13 @@ with gr.Blocks(
1960
  outputs=[url3, url4, add_url_btn, remove_url_btn, url_count]
1961
  )
1962
 
1963
- # Connect RAG functionality
1964
- enable_vector_rag.change(
1965
- toggle_rag_section,
1966
- inputs=[enable_vector_rag],
1967
- outputs=[rag_section]
1968
- )
1969
-
1970
- process_btn.click(
1971
- process_documents,
1972
- inputs=[file_upload, rag_tool_state],
1973
- outputs=[rag_status, rag_tool_state]
1974
- )
1975
 
1976
 
1977
  # Connect the generate button
1978
  generate_btn.click(
1979
  on_generate,
1980
- inputs=[name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, access_code, enable_dynamic_urls, url1, url2, url3, url4, enable_vector_rag, rag_tool_state],
1981
  outputs=[status, download_file, sandbox_state]
1982
  )
1983
 
@@ -2073,7 +1958,7 @@ with gr.Blocks(
2073
 
2074
  preview_export_btn.click(
2075
  export_preview_conversation,
2076
- inputs=[preview_chatbot],
2077
  outputs=[export_file]
2078
  )
2079
 
@@ -2096,8 +1981,8 @@ with gr.Blocks(
2096
  # Connect cross-tab functionality after all components are defined
2097
  preview_btn.click(
2098
  on_preview_combined,
2099
- inputs=[name, description, system_prompt, model, temperature, max_tokens, examples_text, enable_dynamic_urls, enable_vector_rag, rag_tool_state, url1, url2, url3, url4],
2100
- outputs=[preview_config_state, preview_status_comp, preview_chat_section_comp, config_display_comp]
2101
  )
2102
 
2103
  if __name__ == "__main__":
 
39
  return "\n\n" + "\n\n".join(context_parts) + "\n\n"
40
  return ""
41
 
42
+ # RAG functionality removed
 
 
 
 
 
 
43
 
44
  # Load environment variables from .env file
45
  load_dotenv()
 
146
  # Get access code from environment variable for security
147
  ACCESS_CODE = os.environ.get("SPACE_ACCESS_CODE", "{access_code}")
148
  ENABLE_DYNAMIC_URLS = {enable_dynamic_urls}
149
+ # RAG functionality removed
 
150
 
151
  # Get API key from environment - customizable variable name with validation
152
  API_KEY = os.environ.get("{api_key_var}")
 
302
  markdown_content = f"""# Conversation Export
303
  Generated on: {{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}}
304
 
305
+ ## Configuration Information
306
 
307
+ **Assistant Name:** {name}
308
+ **Description:** {description}
309
+ **Model:** {{MODEL}}
310
+ **Temperature:** {temperature}
311
+ **Max Tokens:** {max_tokens}
312
+ **API Key Variable:** {api_key_var}
313
  """
314
 
315
+ # Add URL grounding information
316
+ if GROUNDING_URLS:
317
+ markdown_content += f"\\n**URL Grounding ({{len(GROUNDING_URLS)}} URLs):**\\n"
318
+ for i, url in enumerate(GROUNDING_URLS, 1):
319
+ markdown_content += f"- URL {{i}}: {{url}}\\n"
320
+
321
+ # Add feature flags
322
+ if ENABLE_DYNAMIC_URLS:
323
+ markdown_content += f"\\n**Dynamic URL Fetching:** Enabled\\n"
324
+
325
+ # Add system prompt
326
+ markdown_content += f"\\n**System Prompt:**\\n```\\n{{SYSTEM_PROMPT}}\\n```\\n"
327
+
328
+ markdown_content += "\\n---\\n\\n"
329
+
330
  message_pair_count = 0
331
  for i, message in enumerate(conversation_history):
332
  if isinstance(message, dict):
 
349
 
350
  return markdown_content
351
 
352
+ # RAG functionality removed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
 
354
  def generate_response(message, history):
355
  """Generate response using OpenRouter API"""
 
369
  # Get grounding context
370
  grounding_context = get_grounding_context()
371
 
372
+ # RAG functionality removed
 
 
 
 
373
 
374
  # If dynamic URLs are enabled, check message for URLs to fetch
375
  if ENABLE_DYNAMIC_URLS:
 
625
 
626
  if ENABLE_DYNAMIC_URLS:
627
  status_parts.append("🔄 **Dynamic URLs:** Enabled")
 
 
 
628
 
629
  if ACCESS_CODE:
630
  status_parts.append("🔐 **Access Control:** Enabled")
 
840
 
841
  return readme_content
842
 
843
+ def create_requirements():
844
  """Generate requirements.txt"""
845
+ return "gradio>=4.44.1\nrequests>=2.32.3\nbeautifulsoup4>=4.12.3\npython-dotenv>=1.0.0"
 
 
 
 
 
 
 
846
 
847
+ def generate_zip(name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, access_code="", enable_dynamic_urls=False, url1="", url2="", url3="", url4=""):
848
  """Generate deployable zip file"""
849
 
850
  # Process examples
 
878
  'examples': examples_json,
879
  'grounding_urls': json.dumps(grounding_urls),
880
  'access_code': "", # Access code stored in environment variable for security
881
+ 'enable_dynamic_urls': enable_dynamic_urls
 
 
882
  }
883
 
884
  # Generate files
 
887
  readme_config = config.copy()
888
  readme_config['access_code'] = access_code or ""
889
  readme_content = create_readme(readme_config)
890
+ requirements_content = create_requirements()
891
 
892
  # Create zip file with clean naming
893
  filename = f"{name.lower().replace(' ', '_').replace('-', '_')}.zip"
 
908
  return filename
909
 
910
  # Define callback functions outside the interface
911
+ # RAG functionality removed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
912
 
913
  def update_sandbox_preview(config_data):
914
  """Update the sandbox preview with generated content"""
 
922
  - **Temperature:** {config_data.get('temperature', 'N/A')}
923
  - **Max Tokens:** {config_data.get('max_tokens', 'N/A')}
924
  - **Dynamic URLs:** {'✅ Enabled' if config_data.get('enable_dynamic_urls') else '❌ Disabled'}
925
+ # RAG functionality removed
926
 
927
  **System Prompt Preview:**
928
  ```
 
957
 
958
  return preview_text, preview_html
959
 
960
+ def on_preview_combined(name, description, system_prompt, model, temperature, max_tokens, examples_text, enable_dynamic_urls, url1="", url2="", url3="", url4=""):
961
  """Generate configuration and return preview updates"""
962
  if not name or not name.strip():
963
  return (
964
  {},
965
  gr.update(value="**Error:** Please provide a Space Title to preview", visible=True),
966
  gr.update(visible=False),
967
+ gr.update(value="Configuration will appear here after preview generation."),
968
+ gr.update(), # preview_url1
969
+ gr.update(), # preview_url2
970
+ gr.update(), # preview_url3
971
+ gr.update(), # preview_url4
972
+ gr.update(), # preview_add_url_btn
973
+ gr.update(), # preview_remove_url_btn
974
+ 2 # preview_url_count
975
  )
976
 
977
  try:
 
981
  {},
982
  gr.update(value="**Error:** Please provide a System Prompt for the assistant", visible=True),
983
  gr.update(visible=False),
984
+ gr.update(value="Configuration will appear here after preview generation."),
985
+ gr.update(), # preview_url1
986
+ gr.update(), # preview_url2
987
+ gr.update(), # preview_url3
988
+ gr.update(), # preview_url4
989
+ gr.update(), # preview_add_url_btn
990
+ gr.update(), # preview_remove_url_btn
991
+ 2 # preview_url_count
992
  )
993
 
994
  final_system_prompt = system_prompt.strip()
 
1006
  'url2': url2,
1007
  'url3': url3,
1008
  'url4': url4,
 
 
1009
  'examples_text': examples_text,
1010
  'preview_ready': True
1011
  }
 
1015
  > *{final_system_prompt[:600]}{'...' if len(final_system_prompt) > 600 else '...'}*
1016
 
1017
  Tip: Try different configurations of your space before generating the deployment package."""
1018
+ config_display = f"""> **Configuration**:
 
 
1019
  - **Name:** {name}
1020
  - **Description:** {description or 'No description provided'}
1021
  - **Model:** {model}
 
1034
  # Show success notification
1035
  gr.Info(f"✅ Preview generated successfully for '{name}'! Switch to Preview tab.")
1036
 
1037
+ # Determine how many URLs are configured
1038
+ url_count = 2 # Start with 2 (always visible)
1039
+ if url3 and url3.strip():
1040
+ url_count = 3
1041
+ if url4 and url4.strip():
1042
+ url_count = 4
1043
+
1044
+ # Update preview URL visibility and button states based on count
1045
+ if url_count == 2:
1046
+ preview_url3_update = gr.update(value=url3, visible=False)
1047
+ preview_url4_update = gr.update(value=url4, visible=False)
1048
+ preview_add_btn_update = gr.update(value="+ Add URLs", interactive=True)
1049
+ preview_remove_btn_update = gr.update(visible=False)
1050
+ elif url_count == 3:
1051
+ preview_url3_update = gr.update(value=url3, visible=True)
1052
+ preview_url4_update = gr.update(value=url4, visible=False)
1053
+ preview_add_btn_update = gr.update(value="+ Add URLs", interactive=True)
1054
+ preview_remove_btn_update = gr.update(visible=True)
1055
+ else: # url_count == 4
1056
+ preview_url3_update = gr.update(value=url3, visible=True)
1057
+ preview_url4_update = gr.update(value=url4, visible=True)
1058
+ preview_add_btn_update = gr.update(value="Max URLs", interactive=False)
1059
+ preview_remove_btn_update = gr.update(visible=True)
1060
+
1061
  return (
1062
  config_data,
1063
  gr.update(value=preview_text, visible=True),
1064
  gr.update(visible=True),
1065
+ gr.update(value=config_display),
1066
+ gr.update(value=url1), # preview_url1
1067
+ gr.update(value=url2), # preview_url2
1068
+ preview_url3_update, # preview_url3
1069
+ preview_url4_update, # preview_url4
1070
+ preview_add_btn_update, # preview_add_url_btn
1071
+ preview_remove_btn_update, # preview_remove_url_btn
1072
+ url_count # preview_url_count
1073
  )
1074
 
1075
  except Exception as e:
 
1077
  {},
1078
  gr.update(value=f"**Error:** {str(e)}", visible=True),
1079
  gr.update(visible=False),
1080
+ gr.update(value="Configuration will appear here after preview generation."),
1081
+ gr.update(), # preview_url1
1082
+ gr.update(), # preview_url2
1083
+ gr.update(), # preview_url3
1084
+ gr.update(), # preview_url4
1085
+ gr.update(), # preview_add_url_btn
1086
+ gr.update(), # preview_remove_url_btn
1087
+ 2 # preview_url_count
1088
  )
1089
 
1090
  def update_preview_display(config_data):
 
1105
  - **Temperature:** {config_data['temperature']}
1106
  - **Max Tokens:** {config_data['max_tokens']}
1107
  - **Dynamic URLs:** {'✅ Enabled' if config_data['enable_dynamic_urls'] else '❌ Disabled'}
1108
+ # RAG functionality removed
1109
 
1110
  **System Prompt:**
1111
  {config_data['system_prompt'][:600]}{'...' if len(config_data['system_prompt']) > 600 else ''}
 
1125
 
1126
  **Features:**
1127
  - **Dynamic URL Fetching:** {'✅ Enabled' if config_data['enable_dynamic_urls'] else '❌ Disabled'}
1128
+ # RAG functionality removed
1129
 
1130
  **System Prompt:**
1131
  ```
 
1185
  grounding_urls = config_urls if any(url for url in config_urls if url) else [url1, url2, url3, url4]
1186
  grounding_context = get_cached_grounding_context([url for url in grounding_urls if url and url.strip()])
1187
 
1188
+ # RAG functionality removed
 
 
 
 
 
 
 
 
 
 
 
 
 
1189
 
1190
  # If dynamic URLs are enabled, check message for URLs to fetch
1191
  dynamic_context = ""
 
1200
  dynamic_context = "\n".join(dynamic_context_parts)
1201
 
1202
  # Build enhanced system prompt with all contexts
1203
+ enhanced_system_prompt = config_data.get('system_prompt', '') + grounding_context + dynamic_context
1204
 
1205
  # Build messages array for the API
1206
  messages = [{"role": "system", "content": enhanced_system_prompt}]
 
1279
  """Clear preview chat"""
1280
  return "", []
1281
 
1282
+ def export_preview_conversation(history, config_data=None):
1283
  """Export preview conversation to markdown"""
1284
  if not history:
1285
  return gr.update(visible=False)
1286
 
1287
+ markdown_content = export_conversation_to_markdown(history, config_data)
1288
 
1289
  # Save to temporary file
1290
  import tempfile
 
1294
 
1295
  return gr.update(value=temp_file, visible=True)
1296
 
1297
+ def on_generate(name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, access_code, enable_dynamic_urls, url1, url2, url3, url4):
1298
  if not name or not name.strip():
1299
  return gr.update(value="Error: Please provide a Space Title", visible=True), gr.update(visible=False), {}
1300
 
1301
 
1302
  try:
 
 
 
 
 
1303
  # Use the system prompt directly (template selector already updates it)
1304
  if not system_prompt or not system_prompt.strip():
1305
  return gr.update(value="Error: Please provide a System Prompt for the assistant", visible=True), gr.update(visible=False), {}
1306
 
1307
  final_system_prompt = system_prompt.strip()
1308
 
1309
+ filename = generate_zip(name, description, final_system_prompt, model, api_key_var, temperature, max_tokens, examples_text, access_code, enable_dynamic_urls, url1, url2, url3, url4)
1310
 
1311
  success_msg = f"""**Deployment package ready!**
1312
 
 
1334
  'temperature': temperature,
1335
  'max_tokens': max_tokens,
1336
  'enable_dynamic_urls': enable_dynamic_urls,
 
1337
  'filename': filename
1338
  }
1339
 
 
1747
 
1748
 
1749
 
1750
+ # RAG functionality removed
 
 
 
 
 
 
1751
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1752
 
1753
  examples_text = gr.Textbox(
1754
  label="Example Prompts (one per line)",
 
1783
  value=1500,
1784
  step=50
1785
  )
1786
+
1787
+ # URL Grounding section
1788
+ gr.Markdown("**URL Grounding (Optional)**")
1789
+ gr.Markdown("Add URLs to provide context. Content will be fetched and added to the system prompt.")
1790
+
1791
+ # Initial URL fields
1792
+ url1 = gr.Textbox(
1793
+ label="URL 1",
1794
+ placeholder="https://example.com/page1",
1795
+ info="First URL for context grounding"
1796
+ )
1797
+
1798
+ url2 = gr.Textbox(
1799
+ label="URL 2",
1800
+ placeholder="https://example.com/page2",
1801
+ info="Second URL for context grounding"
1802
+ )
1803
+
1804
+ # Additional URL fields (initially hidden)
1805
+ url3 = gr.Textbox(
1806
+ label="URL 3",
1807
+ placeholder="https://example.com/page3",
1808
+ info="Third URL for context grounding",
1809
+ visible=False
1810
+ )
1811
+
1812
+ url4 = gr.Textbox(
1813
+ label="URL 4",
1814
+ placeholder="https://example.com/page4",
1815
+ info="Fourth URL for context grounding",
1816
+ visible=False
1817
+ )
1818
+
1819
+ # URL management buttons
1820
+ with gr.Row():
1821
+ add_url_btn = gr.Button("+ Add URLs", size="sm")
1822
+ remove_url_btn = gr.Button("- Remove URLs", size="sm", visible=False)
1823
+ url_count = gr.State(2) # Track number of visible URLs
1824
 
1825
  with gr.Row():
1826
  preview_btn = gr.Button("Preview Deployment Package", variant="secondary")
 
1856
  outputs=[url3, url4, add_url_btn, remove_url_btn, url_count]
1857
  )
1858
 
1859
+ # RAG functionality removed
 
 
 
 
 
 
 
 
 
 
 
1860
 
1861
 
1862
  # Connect the generate button
1863
  generate_btn.click(
1864
  on_generate,
1865
+ inputs=[name, description, system_prompt, model, api_key_var, temperature, max_tokens, examples_text, access_code, enable_dynamic_urls, url1, url2, url3, url4],
1866
  outputs=[status, download_file, sandbox_state]
1867
  )
1868
 
 
1958
 
1959
  preview_export_btn.click(
1960
  export_preview_conversation,
1961
+ inputs=[preview_chatbot, preview_config_state],
1962
  outputs=[export_file]
1963
  )
1964
 
 
1981
  # Connect cross-tab functionality after all components are defined
1982
  preview_btn.click(
1983
  on_preview_combined,
1984
+ inputs=[name, description, system_prompt, model, temperature, max_tokens, examples_text, enable_dynamic_urls, url1, url2, url3, url4],
1985
+ outputs=[preview_config_state, preview_status_comp, preview_chat_section_comp, config_display_comp, preview_url1, preview_url2, preview_url3, preview_url4, preview_add_url_btn, preview_remove_url_btn, preview_url_count]
1986
  )
1987
 
1988
  if __name__ == "__main__":
requirements.txt CHANGED
@@ -1,11 +1,4 @@
1
  gradio>=4.44.1
2
  requests>=2.32.3
3
  beautifulsoup4>=4.12.3
4
- python-dotenv>=1.0.0
5
-
6
- # Vector RAG dependencies (optional)
7
- sentence-transformers>=2.2.2
8
- faiss-cpu>=1.11.0
9
- PyMuPDF>=1.23.0
10
- python-docx>=0.8.11
11
- numpy>=1.25.0,<3.0
 
1
  gradio>=4.44.1
2
  requests>=2.32.3
3
  beautifulsoup4>=4.12.3
4
+ python-dotenv>=1.0.0
 
 
 
 
 
 
 
support_docs.py CHANGED
@@ -25,7 +25,7 @@ def create_support_docs():
25
  **Workflow Steps:**
26
  1. **Configure your Space** in the Configuration tab (space title, description, model selection)
27
  2. **Set up Assistant** with system prompt and optional research template
28
- 3. **Enable Tools** like web search, document RAG, or URL grounding as needed
29
  4. **Preview & Test** using the Preview tab to validate your configuration
30
  5. **Generate Package** with the "Generate Deployment Package" button
31
  6. **Deploy to HuggingFace** following the included README instructions
@@ -213,7 +213,7 @@ def create_support_docs():
213
  - **System Prompt**: Main field defining assistant behavior and knowledge
214
  - **Research Template**: Pre-configured academic research assistant checkbox
215
  - **Web Search Integration**: Enable crawl4ai web search capabilities
216
- - **Document RAG**: Upload documents for knowledge base (PDF/DOCX/TXT/MD support)
217
  - **URL Grounding**: Add up to 4 static URLs for context (dynamic add/remove)
218
  - **Example Prompts**: Clickable suggestions for users (one per line)
219
  - **Dynamic URL Fetching**: Hidden field (always enabled) for runtime URL processing
@@ -233,11 +233,7 @@ def create_support_docs():
233
  - Advanced content extraction and crawling
234
  - Automatically enabled with Research Template
235
 
236
- **Document RAG (Vector Search)**
237
- - Upload files: PDF, DOCX, TXT, MD (10MB max each)
238
- - Semantic chunking and FAISS vector search
239
- - Embedded in deployment package for offline use
240
- - Requires `sentence-transformers` and `faiss-cpu`
241
 
242
  **URL Grounding (Static Context)**
243
  - Add 2-4 URLs for consistent context across all responses
@@ -270,7 +266,7 @@ def create_support_docs():
270
 
271
  **Token Usage Notes:**
272
  - Tokens include both input (your prompt + context) and output
273
- - Longer contexts (documents, URLs) use more input tokens
274
  - Consider costs when setting high token limits
275
  """)
276
 
@@ -359,10 +355,7 @@ def create_support_docs():
359
  - Check for typos in the access code
360
  - Case-sensitive matching
361
 
362
- **Documents not loading (RAG)**
363
- - Check file formats are supported (PDF, DOCX, TXT, MD)
364
- - Verify file sizes are under 10MB
365
- - Ensure RAG dependencies are installed
366
 
367
  **URLs not fetching content**
368
  - Check URLs are publicly accessible
@@ -378,7 +371,7 @@ def create_support_docs():
378
  - Use appropriate model for your use case
379
  - Set reasonable token limits
380
  - Cache static content with URL grounding
381
- - Limit document uploads to essential materials
382
 
383
  **User Experience**
384
  - Write clear, helpful example prompts
 
25
  **Workflow Steps:**
26
  1. **Configure your Space** in the Configuration tab (space title, description, model selection)
27
  2. **Set up Assistant** with system prompt and optional research template
28
+ 3. **Enable Tools** like dynamic URL fetching or URL grounding as needed
29
  4. **Preview & Test** using the Preview tab to validate your configuration
30
  5. **Generate Package** with the "Generate Deployment Package" button
31
  6. **Deploy to HuggingFace** following the included README instructions
 
213
  - **System Prompt**: Main field defining assistant behavior and knowledge
214
  - **Research Template**: Pre-configured academic research assistant checkbox
215
  - **Web Search Integration**: Enable crawl4ai web search capabilities
216
+ # Document RAG functionality removed
217
  - **URL Grounding**: Add up to 4 static URLs for context (dynamic add/remove)
218
  - **Example Prompts**: Clickable suggestions for users (one per line)
219
  - **Dynamic URL Fetching**: Hidden field (always enabled) for runtime URL processing
 
233
  - Advanced content extraction and crawling
234
  - Automatically enabled with Research Template
235
 
236
+ # Document RAG functionality removed
 
 
 
 
237
 
238
  **URL Grounding (Static Context)**
239
  - Add 2-4 URLs for consistent context across all responses
 
266
 
267
  **Token Usage Notes:**
268
  - Tokens include both input (your prompt + context) and output
269
+ - Longer contexts (URLs) use more input tokens
270
  - Consider costs when setting high token limits
271
  """)
272
 
 
355
  - Check for typos in the access code
356
  - Case-sensitive matching
357
 
358
+ # Document RAG functionality removed
 
 
 
359
 
360
  **URLs not fetching content**
361
  - Check URLs are publicly accessible
 
371
  - Use appropriate model for your use case
372
  - Set reasonable token limits
373
  - Cache static content with URL grounding
374
+ # Document RAG functionality removed
375
 
376
  **User Experience**
377
  - Write clear, helpful example prompts