Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from streamlit_webrtc import webrtc_streamer, WebRtcMode | |
| import requests | |
| import openai | |
| import tempfile | |
| import logging | |
| # Set logging level for debugging purposes | |
| logging.basicConfig(level=logging.INFO) | |
| # Load API keys from Streamlit secrets | |
| TAVUS_API_KEY = st.secrets.get("TAVUS_API_KEY") | |
| OPENAI_API_KEY = st.secrets.get("OPENAI_API_KEY") | |
| openai.api_key = OPENAI_API_KEY | |
| # Introduction prompt | |
| initial_prompt = "Hello there, I'm Nathan and I'm going to help you with college admissions. How's it going?" | |
| # Initialize conversation history if not present | |
| if 'conversation_history' not in st.session_state: | |
| st.session_state.conversation_history = [{"role": "assistant", "content": initial_prompt}] | |
| def main(): | |
| st.title("AI Video Chatbot for University Admissions") | |
| rtc_configuration = { | |
| "iceServers": [ | |
| {"urls": ["stun:stun.l.google.com:19302"]}, | |
| # Add TURN server details if necessary for restrictive networks | |
| ] | |
| } | |
| # Webrtc streamer without unsupported arguments | |
| webrtc_ctx = webrtc_streamer( | |
| key="user_stream", | |
| mode=WebRtcMode.SENDRECV, | |
| rtc_configuration=rtc_configuration, | |
| media_stream_constraints={ | |
| "audio": True, | |
| "video": True, | |
| }, | |
| video_html_attrs={ | |
| "autoPlay": True, | |
| "controls": False, | |
| "muted": True, | |
| "playsinline": True, | |
| }, | |
| ) | |
| if webrtc_ctx and webrtc_ctx.state.playing: | |
| st.write("Streaming...") | |
| if len(st.session_state.conversation_history) == 1: | |
| avatar_speak_tavus(initial_prompt) | |
| if webrtc_ctx.audio_receiver: | |
| try: | |
| audio_frames = webrtc_ctx.audio_receiver.get_frames(timeout=1) | |
| if audio_frames: | |
| audio_data = b"".join(frame.to_ndarray().tobytes() for frame in audio_frames) | |
| user_text = speech_to_text(audio_data) | |
| if user_text: | |
| st.write(f"**You said:** {user_text}") | |
| st.session_state.conversation_history.append({"role": "user", "content": user_text}) | |
| response = get_chatbot_response(st.session_state.conversation_history) | |
| st.session_state.conversation_history.append({"role": "assistant", "content": response}) | |
| avatar_speak_tavus(response) | |
| except Exception as e: | |
| st.error(f"Error in processing audio: {e}") | |
| # Convert speech to text using OpenAI Whisper API | |
| def speech_to_text(audio_data): | |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmpfile: | |
| tmpfile.write(audio_data) | |
| tmpfile_path = tmpfile.name | |
| try: | |
| with open(tmpfile_path, "rb") as audio_file: | |
| transcript = openai.Audio.transcribe("whisper-1", audio_file) | |
| return transcript.get("text", "") | |
| except Exception as e: | |
| st.error(f"Error during transcription: {e}") | |
| return "" | |
| # Get chatbot response using GPT-3.5 | |
| def get_chatbot_response(conversation_history): | |
| try: | |
| response = openai.ChatCompletion.create( | |
| model="gpt-3.5-turbo", | |
| messages=conversation_history, | |
| max_tokens=150, | |
| ) | |
| return response.choices[0].message["content"] | |
| except Exception as e: | |
| st.error(f"Error in generating response from GPT-3.5: {e}") | |
| return "Sorry, I'm having trouble understanding you at the moment." | |
| # Make Tavus avatar speak the response | |
| def avatar_speak_tavus(text): | |
| try: | |
| url = "https://api.tavus.io/v2/conversations" | |
| headers = { | |
| "Authorization": f"Bearer {TAVUS_API_KEY}", | |
| "Content-Type": "application/json", | |
| } | |
| payload = { | |
| "replica_id": "r79e1c033f", # Replace with your Tavus replica ID | |
| "persona_id": "p9a95912", # Replace with your Tavus persona ID | |
| "conversation_name": "University Admissions Chat", | |
| "conversational_context": text, | |
| "properties": { | |
| "enable_recording": True | |
| } | |
| } | |
| response = requests.post(url, headers=headers, json=payload) | |
| if response.status_code == 200: | |
| video_url = response.json().get("conversation_url") | |
| if video_url: | |
| st.video(video_url) | |
| else: | |
| st.error("No video URL received from Tavus API.") | |
| else: | |
| st.error(f"Error from Tavus API: {response.status_code} {response.text}") | |
| except Exception as e: | |
| st.error(f"Error in Tavus speech generation: {e}") | |
| if __name__ == "__main__": | |
| main() | |