diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5bb3782 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +``` +# Backup files +*.py.bak +``` \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..a5b440c --- /dev/null +++ b/app.py @@ -0,0 +1,54 @@ +import streamlit as st + +# Set page configuration +st.set_page_config( + page_title="Clean Streamlit UI", + page_icon="✨", + layout="wide", + initial_sidebar_state="auto" +) + +# Main title +st.title("✨ Clean Streamlit UI") +st.subheader("A simple, elegant interface") + +# Simple form +with st.form("simple_form"): + st.write("Enter some information below:") + + name = st.text_input("Name", placeholder="Enter your name") + email = st.text_input("Email", placeholder="Enter your email") + message = st.text_area("Message", placeholder="Enter your message here...") + + submitted = st.form_submit_button("Submit") + + if submitted: + if name and email and message: + st.success(f"Thank you {name}! Your message has been received.") + st.balloons() + else: + st.error("Please fill in all fields.") + +# Add some spacing +st.divider() + +# Simple columns layout +col1, col2 = st.columns(2) + +with col1: + st.header("Features") + st.write("- Simple and clean design") + st.write("- Easy to use interface") + st.write("- Responsive layout") + st.write("- Minimal dependencies") + +with col2: + st.header("Usage") + st.write("1. Fill in the form") + st.write("2. Click submit") + st.write("3. View results") + st.write("4. Enjoy simplicity!") + +# Footer +st.divider() +st.caption("Built with â¤ī¸ using Streamlit") \ No newline at end of file diff --git a/streamlit-tts-agent.py b/streamlit-tts-agent.py deleted file mode 100644 index 3e9b980..0000000 --- a/streamlit-tts-agent.py +++ /dev/null @@ -1,982 +0,0 @@ -import streamlit as st -import requests -import json -import base64 -from io import BytesIO -import os -import hashlib -import time -from datetime import datetime, timedelta -import sqlite3 -from contextlib import contextmanager -import logging -from typing import Dict, Any, Optional -import secrets - -# ------------------------------------------------------- -# Configuration & Constants -# ------------------------------------------------------- -DB_PATH = "enterprise_ai_agent.db" -LOG_LEVEL = logging.INFO -LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" - -# Initialize logging -logging.basicConfig(level=LOG_LEVEL, format=LOG_FORMAT) -logger = logging.getLogger(__name__) - -# ------------------------------------------------------- -# Database Setup (for usage tracking only) -# ------------------------------------------------------- -def init_db(): - conn = sqlite3.connect(DB_PATH) - c = conn.cursor() - - # Usage logs (no user authentication needed) - c.execute(''' - CREATE TABLE IF NOT EXISTS usage_logs ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - session_id TEXT NOT NULL, - service_type TEXT NOT NULL, - input_text TEXT, - output_text TEXT, - media_url TEXT, - timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ip_address TEXT - ) - ''') - - conn.commit() - conn.close() - -# ------------------------------------------------------- -# Session Management -# ------------------------------------------------------- -def get_session_id(): - if 'session_id' not in st.session_state: - st.session_state.session_id = secrets.token_hex(16) - return st.session_state.session_id - -def log_usage(session_id: str, service_type: str, input_text: str, output_text: str, media_url: str = None, ip_address: str = "unknown"): - conn = sqlite3.connect(DB_PATH) - c = conn.cursor() - c.execute(''' - INSERT INTO usage_logs (session_id, service_type, input_text, output_text, media_url, ip_address) - VALUES (?, ?, ?, ?, ?, ?) - ''', (session_id, service_type, input_text, output_text, media_url, ip_address)) - conn.commit() - conn.close() - -# ------------------------------------------------------- -# Enhanced Custom CSS with Modern Enterprise Design -# ------------------------------------------------------- -st.markdown(""" - -""", unsafe_allow_html=True) - -# Initialize database -init_db() - -# ------------------------------------------------------- -# Initialize Session State -# ------------------------------------------------------- -if 'generated_text' not in st.session_state: - st.session_state.generated_text = "" -if 'media_result' not in st.session_state: - st.session_state.media_result = None -if 'api_keys' not in st.session_state: - st.session_state.api_keys = {} - -# Get session ID for usage tracking -session_id = get_session_id() - -# ------------------------------------------------------- -# Sidebar API Keys - Enhanced Design -# ------------------------------------------------------- -with st.sidebar: - # Sidebar Header - st.markdown(""" -
-
🔑
-

API Configuration

-

Enter only the keys you need

-
- """, unsafe_allow_html=True) - - st.markdown("
", unsafe_allow_html=True) - - # Required Section - Claude - st.markdown(""" -
-
- ⚡ - Required: Text Generation -
-
- Enter your Claude API key to enable AI text generation -
-
- """, unsafe_allow_html=True) - - claude_key = st.text_input( - "Claude API Key (Anthropic)", - type="password", - key="claude_key", - placeholder="sk-ant-api03-...", - help="Get your key from console.anthropic.com" - ) - - if claude_key: - st.markdown(""" -
-
- ✓ Claude API key configured -
-
- """, unsafe_allow_html=True) - - st.markdown("
", unsafe_allow_html=True) - - # Optional Models Expander - with st.expander("🔧 Optional: Additional LLM Models", expanded=False): - st.markdown(""" -
- Add more AI models for variety. These are completely optional. -
- """, unsafe_allow_html=True) - - openai_key = st.text_input( - "OpenAI GPT-4", - type="password", - key="openai_key", - placeholder="sk-...", - help="For GPT-4 text generation" - ) - - google_key = st.text_input( - "Google Gemini", - type="password", - key="google_key", - placeholder="AIza...", - help="For Gemini text generation" - ) - - hf_key = st.text_input( - "HuggingFace", - type="password", - key="hf_key", - placeholder="hf_...", - help="For Llama-2 text generation" - ) - - st.markdown("
", unsafe_allow_html=True) - st.markdown("
", unsafe_allow_html=True) - - # Audio/Video Section - st.markdown(""" -
-
- đŸŽĩ - Audio/Video Generation -
-
- Choose your preferred TTS provider -
-
- """, unsafe_allow_html=True) - - # TTS Provider Selection with custom styling - tts_choice = st.radio( - "Select Provider:", - ["OpenAI TTS (Recommended)", "ElevenLabs", "D-ID Video"], - help="Choose the service for converting text to audio/video", - label_visibility="visible" - ) - - st.markdown("
", unsafe_allow_html=True) - - # Show appropriate key input based on selection - if tts_choice == "OpenAI TTS (Recommended)": - if openai_key: - openai_tts_key = openai_key - st.markdown(""" -
-
- ✓ Reusing OpenAI key from above -
-
- """, unsafe_allow_html=True) - else: - st.markdown(""" -
-
- â„šī¸ Need OpenAI key for TTS -
-
- """, unsafe_allow_html=True) - openai_tts_key = st.text_input( - "OpenAI API Key", - type="password", - key="openai_tts_key", - placeholder="sk-...", - help="Same as OpenAI GPT-4 key" - ) - - elif tts_choice == "ElevenLabs": - st.markdown(""" -
-
- â„šī¸ Professional voice synthesis -
-
- """, unsafe_allow_html=True) - elevenlabs_key = st.text_input( - "ElevenLabs API Key", - type="password", - key="elevenlabs_key", - placeholder="Enter your ElevenLabs key", - help="Get from elevenlabs.io" - ) - - else: # D-ID Video - st.markdown(""" -
-
- â„šī¸ AI avatar video generation -
-
- """, unsafe_allow_html=True) - did_key = st.text_input( - "D-ID API Key", - type="password", - key="did_key", - placeholder="Enter your D-ID key", - help="Get from d-id.com" - ) - - # Help Section - st.markdown("
", unsafe_allow_html=True) - - with st.expander("📚 How to Get API Keys", expanded=False): - st.markdown(""" -
-
-
🔮 Claude (Primary)
- 1. Visit console.anthropic.com
- 2. Sign up / Log in
- 3. Go to API Keys section
- 4. Create new key -
- -
-
🤖 OpenAI
- Visit platform.openai.com -
- -
-
✨ Gemini
- Visit makersuite.google.com -
- -
-
🔊 ElevenLabs
- Visit elevenlabs.io -
-
- """, unsafe_allow_html=True) - - # Stats/Info at bottom - st.markdown(""" -
-
- 💡 Quick Tips -
-
- â€ĸ Keys are stored in browser only
- â€ĸ Start with Claude + OpenAI TTS
- â€ĸ Add more models as needed
- â€ĸ All data is secure & private -
-
- """, unsafe_allow_html=True) - -# ------------------------------------------------------- -# Main Header -# ------------------------------------------------------- -st.markdown(""" -
-
-
đŸŽ™ī¸
-
-

Enterprise AI Agent

-

Powered by Claude AI → Convert to Audio/Video

-
-
-
-""", unsafe_allow_html=True) - -# ------------------------------------------------------- -# Two-Column Layout for Steps -# ------------------------------------------------------- -col1, col2 = st.columns(2, gap="large") - -with col1: - st.markdown(""" -
-
- 🧠 - Step 1: AI Text Generation -
-
- """, unsafe_allow_html=True) - - # Determine available models based on API keys - available_models = [] - if claude_key: - available_models.append("claude") - if openai_key: - available_models.append("openai") - if google_key: - available_models.append("gemini") - if hf_key: - available_models.append("huggingface") - - # Default to claude if available - if not available_models: - st.warning("âš ī¸ Please enter at least one LLM API key in the sidebar") - available_models = ["claude"] # Show option even if no key - - llm_model = st.selectbox( - "Select LLM Model", - available_models, - format_func=lambda x: { - "claude": "🔮 Claude 3.5 Sonnet (Recommended)", - "openai": "🤖 OpenAI GPT-4", - "gemini": "✨ Google Gemini", - "huggingface": "🤗 Llama-2" - }.get(x, x) - ) - - enhance_mode = st.selectbox( - "Enhancement Mode", - ["improve", "script", "narration", "podcast", "story", "professional", "casual"], - format_func=lambda x: { - "improve": "âœī¸ Improve & Enhance", - "script": "đŸŽŦ Video Script", - "narration": "📖 Narration Style", - "podcast": "đŸŽ™ī¸ Podcast Intro", - "story": "📚 Expand into Story", - "professional": "đŸ’ŧ Professional Tone", - "casual": "😊 Casual & Friendly" - }[x] - ) - -with col2: - st.markdown(""" -
-
- đŸŽĩ - Step 2: Audio/Video Generation -
-
- """, unsafe_allow_html=True) - - # Map radio choice to model name - tts_model_map = { - "OpenAI TTS (Recommended)": "openai-tts", - "ElevenLabs": "elevenlabs", - "D-ID Video": "did" - } - tts_model = tts_model_map[tts_choice] - - st.info(f"📌 Using: **{tts_choice}**") - - voices = { - "openai-tts": ["alloy", "echo", "fable", "onyx", "nova", "shimmer"], - "elevenlabs": ["Rachel", "Drew", "Clyde", "Paul", "Domi", "Dave"], - "did": ["en-US-JennyNeural", "en-US-GuyNeural"] - } - - voice = st.selectbox("Voice Selection", voices[tts_model]) - -st.markdown("
", unsafe_allow_html=True) - -# ------------------------------------------------------- -# Text Input Section -# ------------------------------------------------------- -st.markdown(""" -
-
- âœī¸ - Enter Your Text -
-
-""", unsafe_allow_html=True) - -input_text = st.text_area( - "", - height=150, - placeholder="Enter your text or topic here... For example: 'Create a professional introduction about AI technology' or 'Write a casual podcast intro about climate change'", - label_visibility="collapsed" -) - -st.caption(f"📝 {len(input_text)} characters") - -# ------------------------------------------------------- -# Enhancement Prompts -# ------------------------------------------------------- -enhance_prompts = { - "improve": "Improve writing and clarity.", - "script": "Convert this into a video script.", - "narration": "Rewrite in narrative storytelling style.", - "podcast": "Rewrite as a podcast intro.", - "story": "Expand into a fictional story.", - "professional": "Rewrite formally and professionally.", - "casual": "Rewrite casually and friendly." -} - -# ------------------------------------------------------- -# LLM Generation Function -# ------------------------------------------------------- -def generate_with_llm(text, model, keys, mode): - prompt = f"{enhance_prompts[mode]}\n\nOriginal text:\n{text}" - - if model == "claude": - if not keys.get("claude"): - raise Exception("Claude API key required. Please add it in the sidebar.") - - r = requests.post( - "https://api.anthropic.com/v1/messages", - headers={ - "x-api-key": keys["claude"], - "anthropic-version": "2023-06-01", - "Content-Type": "application/json" - }, - json={ - "model": "claude-3-5-sonnet-20241022", - "max_tokens": 1024, - "messages": [{"role": "user", "content": prompt}] - } - ) - - data = r.json() - if "error" in data: - raise Exception(f"Claude Error: {data['error'].get('message', 'Unknown error')}") - return data["content"][0]["text"] - - elif model == "openai": - if not keys.get("openai"): - raise Exception("OpenAI API key required") - - r = requests.post( - "https://api.openai.com/v1/chat/completions", - headers={ - "Authorization": f"Bearer {keys['openai']}", - "Content-Type": "application/json", - }, - json={ - "model": "gpt-4o-mini", - "messages": [ - {"role": "system", "content": "You are a text enhancement AI."}, - {"role": "user", "content": prompt}, - ], - }, - ) - - data = r.json() - if "error" in data: - raise Exception(f"OpenAI Error: {data['error']['message']}") - return data["choices"][0]["message"]["content"] - - elif model == "gemini": - if not keys.get("google"): - raise Exception("Gemini API key required") - - url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key={keys['google']}" - r = requests.post(url, json={"contents": [{"parts": [{"text": prompt}]}]}) - - data = r.json() - if "error" in data: - raise Exception(f"Gemini Error: {data['error']['message']}") - return data["candidates"][0]["content"]["parts"][0]["text"] - - elif model == "huggingface": - if not keys.get("huggingface"): - raise Exception("HuggingFace key required") - - r = requests.post( - "https://api-inference.huggingface.co/models/meta-llama/Llama-2-70b-chat-hf", - headers={"Authorization": f"Bearer {keys['huggingface']}"}, - json={"inputs": prompt}, - ) - - data = r.json() - if isinstance(data, dict) and "error" in data: - raise Exception(f"HuggingFace Error: {data['error']}") - return data[0]["generated_text"] - -# ------------------------------------------------------- -# Media Generation Function -# ------------------------------------------------------- -def generate_media(text, model, voice, keys): - if model == "openai-tts": - api_key = keys.get("openai") or keys.get("openai_tts") - if not api_key: - raise Exception("OpenAI API key required for TTS") - - r = requests.post( - "https://api.openai.com/v1/audio/speech", - headers={ - "Authorization": f"Bearer {api_key}", - "Content-Type": "application/json" - }, - json={"model": "tts-1-hd", "voice": voice, "input": text} - ) - - if r.status_code != 200: - raise Exception(f"OpenAI TTS Error: {r.text}") - - return {"type": "audio", "content": r.content} - - elif model == "elevenlabs": - if not keys.get("elevenlabs"): - raise Exception("ElevenLabs API key required") - - voices_map = { - "Rachel": "21m00Tcm4TlvDq8ikWAM", - "Drew": "29vD33N1CtxCmqQRPOHJ", - "Clyde": "2EiwWnXFnvU5JabPnv8n", - "Paul": "5Q0t7uMcjvnagumLfvZi", - "Domi": "AZnzlk1XvdvUeBnXmlld", - "Dave": "CYw3kZ02Hs0563khs1Fj", - } - - r = requests.post( - f"https://api.elevenlabs.io/v1/text-to-speech/{voices_map[voice]}", - headers={"xi-api-key": keys["elevenlabs"]}, - json={"text": text} - ) - - if r.status_code != 200: - raise Exception(f"ElevenLabs Error: {r.text}") - - return {"type": "audio", "content": r.content} - - elif model == "did": - if not keys.get("did"): - raise Exception("D-ID API key required") - - did_auth = base64.b64encode(f"{keys['did']}:".encode()).decode() - - r = requests.post( - "https://api.d-id.com/talks", - headers={ - "Authorization": f"Basic {did_auth}", - "Content-Type": "application/json" - }, - json={ - "script": { - "type": "text", - "input": text, - "voice_id": voice, - "provider": {"type": "microsoft"} - }, - "source_url": "https://create-images-results.d-id.com/default-presenter.jpg" - } - ) - - if r.status_code != 201: - raise Exception(f"D-ID Error: {r.text}") - - data = r.json() - return {"type": "video", "url": data.get("result_url")} - -# ------------------------------------------------------- -# Generate Button -# ------------------------------------------------------- -st.markdown("
", unsafe_allow_html=True) - -if st.button("✨ Generate AI Content → Audio/Video"): - if not input_text.strip(): - st.error("âš ī¸ Please enter some text first") - else: - # Collect only provided API keys - keys = {} - if claude_key: - keys["claude"] = claude_key - if openai_key: - keys["openai"] = openai_key - if google_key: - keys["google"] = google_key - if hf_key: - keys["huggingface"] = hf_key - - # Add TTS keys - if tts_model == "openai-tts": - if 'openai_tts_key' in locals(): - keys["openai_tts"] = openai_tts_key - elif tts_model == "elevenlabs" and 'elevenlabs_key' in locals(): - keys["elevenlabs"] = elevenlabs_key - elif tts_model == "did" and 'did_key' in locals(): - keys["did"] = did_key - - try: - # Step 1: Generate Enhanced Text - with st.spinner("🧠 Generating enhanced text with AI..."): - enhanced = generate_with_llm(input_text, llm_model, keys, enhance_mode) - st.session_state.generated_text = enhanced - - st.success("✅ Text enhanced successfully!") - - # Step 2: Generate Media - with st.spinner("đŸŽ™ī¸ Converting to audio/video..."): - media = generate_media(enhanced, tts_model, voice, keys) - st.session_state.media_result = media - - st.success("✅ Media generated successfully!") - - # Log usage (anonymous) - media_url = media.get('url', None) if media.get('type') == 'video' else None - log_usage(session_id, f"{llm_model}+{tts_model}", input_text, enhanced, media_url) - - except Exception as e: - st.error(f"❌ Error: {str(e)}") - -# ------------------------------------------------------- -# Display Results -# ------------------------------------------------------- -if st.session_state.generated_text: - st.markdown("
", unsafe_allow_html=True) - st.markdown(""" -
-
- 🧠 - AI Enhanced Text -
-
- """, unsafe_allow_html=True) - - st.text_area("", st.session_state.generated_text, height=180, label_visibility="collapsed", disabled=True) - -if st.session_state.media_result: - st.markdown("
", unsafe_allow_html=True) - st.markdown(""" -
-
- đŸŽĩ - Generated Content -
-
- """, unsafe_allow_html=True) - - media = st.session_state.media_result - - if media["type"] == "audio": - st.audio(media["content"], format="audio/mp3") - st.download_button( - "âŦ‡ī¸ Download Audio", - media["content"], - "generated_audio.mp3", - "audio/mp3" - ) - - elif media["type"] == "video": - if media.get("url"): - st.video(media["url"]) - st.markdown(f"[đŸ“Ĩ Download Video]({media['url']})") - else: - st.error("❌ D-ID returned no video URL") - -# ------------------------------------------------------- -# Footer -# ------------------------------------------------------- -st.markdown(""" - -""", unsafe_allow_html=True)