import streamlit as st import os from groq import Groq from datetime import datetime import re import json import hashlib # Page configuration st.set_page_config( page_title="AI Artifact Chat", page_icon="💬", layout="wide", initial_sidebar_state="expanded" ) # Initialize session state if "messages" not in st.session_state: st.session_state.messages = [] if "artifacts" not in st.session_state: st.session_state.artifacts = [] if "conversation_start" not in st.session_state: st.session_state.conversation_start = datetime.now() if "system_prompt" not in st.session_state: st.session_state.system_prompt = """You are a helpful assistant that generates content in various formats including HTML, React components, and Three.js visualizations. When showing code examples, always use markdown code blocks with appropriate language tags (e.g. ```html, ```javascript, ```jsx).""" def clean_and_format_code(response): """Clean and format the code from the response""" # Remove thinking tags thinking_patterns = [ r'.*?', r'.*?', r'.*?', r'.*?', r'.*?' ] for pattern in thinking_patterns: response = re.sub(pattern, '', response, flags=re.DOTALL) # Remove markdown-style emphasis response = re.sub(r'\*\*(.*?)\*\*', r'\1', response) # Remove **bold** response = re.sub(r'\*(.*?)\*', r'\1', response) # Remove *italic* # If the response contains both script and HTML elements, wrap it in HTML structure if ' 3D Visualization {response} """ return response.strip() def extract_code_and_type(response): """Extract code blocks and determine artifact type""" # First, clean and format the code response = clean_and_format_code(response) # Look for code blocks first code_blocks = list(re.finditer(r'```(\w+)?\n(.*?)```', response, flags=re.DOTALL)) if code_blocks: html_code = None js_code = None react_code = None for block in code_blocks: lang = block.group(1).lower() if block.group(1) else '' code = block.group(2).strip() if lang in ['html', 'htm']: html_code = code elif lang in ['javascript', 'js']: js_code = code elif lang in ['jsx', 'react', 'tsx']: react_code = code return code, "application/vnd.ant.react" # Combine HTML and JavaScript if both exist if html_code and js_code: if '' in html_code: combined = html_code.replace('', f'') else: combined = f"{html_code}" return combined, "text/html" elif html_code: return html_code, "text/html" elif js_code: return js_code, "application/vnd.ant.react" # If no code blocks found but content contains HTML/script tags if '.*?', r'.*?', r'.*?', r'.*?', r'.*?' ] for pattern in thinking_patterns: response = re.sub(pattern, '', response, flags=re.DOTALL) # Clean up extra newlines response = re.sub(r'\n\s*\n\s*\n', '\n\n', response) # Try to extract code and determine type artifact_content, artifact_type = extract_code_and_type(response) if artifact_content: # Generate artifact ID artifact_id = hashlib.md5(artifact_content.encode()).hexdigest()[:8] # Store artifact st.session_state.artifacts.append({ "id": artifact_id, "type": artifact_type, "content": artifact_content, "created_at": datetime.now().isoformat() }) # Add assistant message with artifact reference st.session_state.messages.append({ "role": "assistant", "content": response.replace(artifact_content, '').strip(), "artifact_id": artifact_id }) else: # Add regular assistant message st.session_state.messages.append({ "role": "assistant", "content": response }) st.rerun()