Spaces:
Running
Running
File size: 5,425 Bytes
5d21581 a03a2cf 5d21581 8ee304b 5d21581 c913bf6 5d21581 c913bf6 5d21581 c913bf6 5d21581 c913bf6 222b009 c913bf6 222b009 fb852ed 5d21581 2a9d572 5d21581 c913bf6 5d21581 c913bf6 5d21581 c913bf6 be80196 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
import streamlit as st
from groq import Groq
from langchain_groq import ChatGroq
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
import edge_tts
import asyncio
import os
from typing import Optional
GROQ_API_KEY = os.getenv('GROQ_API_KEY')
class CodeAssistantBot:
def __init__(self):
self.client = Groq(api_key=GROQ_API_KEY)
self.model = ChatGroq(model="llama-3.3-70b-versatile", temperature=0.6)
# Initialize prompts
self.analysis_prompt = ChatPromptTemplate.from_messages([
("system",
"""You are an expert code assistant. Analyze the code and context provided,
then give clear, helpful responses. Keep responses concise and focused on the code."""
),
("user", """Code: {code}
Output: {output}
Error: {error}
Question: {question}""")
])
self.summary_prompt = ChatPromptTemplate.from_messages([(
"system",
"""Summarize the conversation focusing on key technical points and insights.
Keep it brief and clear."""
), ("user", "Conversation: {conversation}")])
def analyze_code(self, code: str, output: str, error: str,
question: str) -> str:
try:
parser = StrOutputParser()
chain = self.analysis_prompt | self.model | parser
return chain.invoke({
'code': code,
'output': output,
'error': error,
'question': question
})
except Exception as e:
return f"Sorry, I encountered an error: {str(e)}"
def summarize_conversation(self, conversation: list) -> str:
try:
parser = StrOutputParser()
chain = self.summary_prompt | self.model | parser
formatted_conv = "\n".join(
[f"Q: {q}\nA: {a}" for q, a in conversation])
return chain.invoke({'conversation': formatted_conv})
except Exception as e:
return f"Could not generate summary: {str(e)}"
async def text_to_speech(text: str, filename: str):
voice = "fr-FR-VivienneMultilingualNeural"
communicate = edge_tts.Communicate(text, voice)
await communicate.save(filename)
def render_chatbot(code: str, output: str, error: str):
"""Render the chatbot UI in a fixed-height, scrollable panel"""
# Initialize session state
if "conversation" not in st.session_state:
st.session_state.conversation = []
if "audio_count" not in st.session_state:
st.session_state.audio_count = 0
# Create bot instance
bot = CodeAssistantBot()
# Apply CSS for scrollable chat window
st.markdown("""
<style>
.chat-container {
height: 500px; /* Fixed height */
overflow-y: auto; /* Scrollable */
border: 1px solid #ddd;
padding: 10px;
background-color: #f9f9f9;
border-radius: 5px;
}
.chat-message {
padding: 10px;
border-radius: 5px;
margin-bottom: 10px;
}
.user-message {
background-color: #e3f2fd;
}
.bot-message {
background-color: #f5f5f5;
}
</style>
""", unsafe_allow_html=True)
# Chat history in a scrollable container
chat_container = st.container()
with chat_container:
st.markdown('<div class="chat-container">', unsafe_allow_html=True)
# Display all chat messages
for q, a in st.session_state.conversation:
st.markdown(f'<div class="chat-message user-message">You: {q}</div>', unsafe_allow_html=True)
st.markdown(f'<div class="chat-message bot-message">Assistant: {a}</div>', unsafe_allow_html=True)
# Close the chat container div
st.markdown('</div>', unsafe_allow_html=True)
# Input area at the bottom
col1, col2 = st.columns([4, 1])
with col1:
user_input = st.text_input("Ask your Question here", key="chat_input", placeholder="Type your question here...")
with col2:
send_clicked = st.button("π") # Button to send the message
if user_input and send_clicked:
# Get response
response = bot.analyze_code(code, output, error, user_input)
st.session_state.conversation.append((user_input, response))
# Generate summary and speech if conversation is long enough
if len(st.session_state.conversation) > 3:
with st.spinner("Generating conversation summary..."):
summary = bot.summarize_conversation(st.session_state.conversation)
audio_file = f"summary_{st.session_state.audio_count}.wav"
asyncio.run(text_to_speech(summary, audio_file))
st.session_state.audio_count += 1
with st.expander("π Conversation Summary", expanded=False):
st.markdown(summary)
st.audio(audio_file, format="audio/wav")
# **Auto-scroll to bottom (forcing UI refresh)**
st.markdown("""
<script>
var chatDiv = window.parent.document.querySelector('.chat-container');
if (chatDiv) {
chatDiv.scrollTop = chatDiv.scrollHeight;
}
</script>
""", unsafe_allow_html=True)
|