vsj0702 commited on
Commit
b8523b7
·
verified ·
1 Parent(s): 16093e8
Files changed (1) hide show
  1. app.py +110 -82
app.py CHANGED
@@ -1,94 +1,122 @@
1
  import streamlit as st
2
- from groq import Groq
3
- from langchain_groq import ChatGroq
4
- from langchain_core.prompts import ChatPromptTemplate
5
- from langchain_core.output_parsers import StrOutputParser
6
- from html import escape
7
- import edge_tts
8
- import asyncio
9
- import os
10
 
11
- GROQ_API_KEY = os.getenv('GROQ_API_KEY')
 
 
 
 
 
12
 
13
- class CodeAssistantBot:
14
- def __init__(self):
15
- self.client = Groq(api_key=GROQ_API_KEY)
16
- self.model = ChatGroq(model="llama-3.3-70b-versatile", temperature=0.6)
17
- self.analysis_prompt = ChatPromptTemplate.from_messages([
18
- ("system", "You are an expert code assistant. Keep responses concise."),
19
- ("user", "Code: {code}\nOutput: {output}\nError: {error}\nQuestion: {question}")
20
- ])
21
- self.summary_prompt = ChatPromptTemplate.from_messages([
22
- ("system", "Summarize key technical points."),
23
- ("user", "Conversation: {conversation}")
24
- ])
25
 
26
- def analyze_code(self, code, output, error, question):
27
- try:
28
- parser = StrOutputParser()
29
- chain = self.analysis_prompt | self.model | parser
30
- return chain.invoke({
31
- 'code': code,
32
- 'output': output,
33
- 'error': error,
34
- 'question': question
35
- })
36
- except Exception as e:
37
- return f"Error: {e}"
38
 
39
- async def text_to_speech(text, filename):
40
- voice = "fr-FR-VivienneMultilingualNeural"
41
- await edge_tts.Communicate(text, voice).save(filename)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
 
 
 
43
 
44
- def render_chatbot(code, output, error):
45
- """Render the chatbot UI with code-block support and no deprecated APIs."""
46
- st.session_state.setdefault('conversation', [])
47
- st.session_state.setdefault('audio_count', 0)
48
 
49
- # Input row
50
- c1, c2 = st.columns([4,1], gap='small')
51
- with c1:
52
- question = st.text_input("Ask your question…", key="chat_input")
53
- with c2:
54
- send = st.button("🚀")
 
 
 
 
 
 
 
55
 
56
- # Handle send
57
- if send and question:
58
- bot = CodeAssistantBot()
59
- response = bot.analyze_code(code, output, error, question)
60
- st.session_state.conversation.append((question, response))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
- # Chat container
63
- st.markdown('<div class="chat-container">', unsafe_allow_html=True)
64
- for q, a in st.session_state.conversation:
65
- # User message
66
- st.markdown(f'<div class="chat-message user-message">{escape(q)}</div>', unsafe_allow_html=True)
67
 
68
- # Bot message with code formatting
69
- def format_response(text):
70
- parts = text.split('```')
71
- result = ''
72
- for i, part in enumerate(parts):
73
- if i % 2 == 1:
74
- # Remove optional language tag
75
- lines = part.splitlines()
76
- if lines and lines[0].isalpha():
77
- lines = lines[1:]
78
- code_html = escape("\n".join(lines))
79
- result += f'<pre><code>{code_html}</code></pre>'
80
- else:
81
- result += escape(part)
82
- return result
83
 
84
- formatted = format_response(a)
85
- st.markdown(f'<div class="chat-message bot-message">{formatted}</div>', unsafe_allow_html=True)
86
- st.markdown('</div>', unsafe_allow_html=True)
87
-
88
- # Auto-scroll
89
- st.markdown("""
90
- <script>
91
- const c = window.parent.document.querySelector('.chat-container');
92
- if (c) c.scrollTop = c.scrollHeight;
93
- </script>
94
- """, unsafe_allow_html=True)
 
1
  import streamlit as st
2
+ import streamlit_ace as st_ace
3
+ from utils import execute_code
4
+ from chatbot import render_chatbot
 
 
 
 
 
5
 
6
+ # Page configuration (must be first)
7
+ st.set_page_config(
8
+ page_title="Pro Code Playground",
9
+ page_icon="💻",
10
+ layout="wide"
11
+ )
12
 
13
+ # Theme toggle
14
+ dm = st.sidebar.checkbox("🌙 Dark mode", value=False)
 
 
 
 
 
 
 
 
 
 
15
 
16
+ # Styling variables
17
+ BG = "#0f1620" if dm else "#f5f5f5"
18
+ PANEL_BG = "#1c2330" if dm else "#ffffff"
19
+ TEXT = "#e3e8f1" if dm else "#1a1a1a"
20
+ ACCENT = "#ff5252"
21
+ BORDER = "#2a3240" if dm else "#dddddd"
22
+ SHADOW = "rgba(0,0,0,0.3)" if dm else "rgba(0,0,0,0.1)"
23
+ ACE_THEME = "monokai" if dm else "chrome"
 
 
 
 
24
 
25
+ # Global CSS
26
+ st.markdown(f"""
27
+ <style>
28
+ .stApp {{ background-color: {BG}; color: {TEXT}; }}
29
+ [data-testid="stSidebar"] {{ background-color: {PANEL_BG} !important; }}
30
+ .ace_editor, .ace_scroller {{
31
+ background: {PANEL_BG} !important;
32
+ box-shadow: 0 4px 8px {SHADOW} !important;
33
+ border-radius: 8px !important;
34
+ }}
35
+ textarea, input, .stTextArea textarea {{
36
+ background: {PANEL_BG} !important;
37
+ color: {TEXT} !important;
38
+ border: 1px solid {BORDER} !important;
39
+ border-radius: 4px !important;
40
+ }}
41
+ button, .stDownloadButton > button {{
42
+ background-color: {ACCENT} !important;
43
+ color: #fff !important;
44
+ border-radius: 6px !important;
45
+ }}
46
+ .chat-container {{ background: {PANEL_BG} !important; border: 1px solid {BORDER} !important; border-radius: 8px !important; padding: 1rem; max-height: 480px; overflow-y: auto; }}
47
+ .chat-message {{ margin-bottom: 1rem; padding: 0.75rem 1rem; border-radius: 12px; }}
48
+ .user-message {{ background: rgba(100,149,237,0.2); align-self: flex-end; }}
49
+ .bot-message {{ background: rgba(200,200,200,0.2); align-self: flex-start; }}
50
+ pre code {{ display: block; padding: 0.5rem; background: rgba(0,0,0,0.1); border-radius: 4px; overflow-x: auto; }}
51
+ </style>
52
+ """, unsafe_allow_html=True)
53
 
54
+ # App header
55
+ st.title("Pro Code Playground")
56
+ st.markdown("Write, execute & export Python snippets, with built‑in AI assistance.")
57
 
58
+ # Main layout
59
+ col1, col2 = st.columns([2, 1], gap="large")
 
 
60
 
61
+ with col1:
62
+ st.subheader("Editor")
63
+ code = st_ace.st_ace(
64
+ placeholder="Start typing Python code…",
65
+ language="python",
66
+ theme=ACE_THEME,
67
+ keybinding="vscode",
68
+ font_size=14,
69
+ min_lines=20,
70
+ show_gutter=True,
71
+ wrap=True,
72
+ auto_update=True
73
+ )
74
 
75
+ # Detect input() calls
76
+ input_calls = code.count("input(")
77
+ inputs = []
78
+ if input_calls:
79
+ st.info(f"Your code expects {input_calls} input(s). Provide them below:")
80
+ for i in range(input_calls):
81
+ val = st.text_input(f"Input #{i+1}", key=f"inp_{i}")
82
+ inputs.append(val)
83
+ if not all(inputs):
84
+ st.warning("Please fill all inputs to run the code.")
85
+
86
+ # Run button
87
+ if st.button("▶️ Run"):
88
+ exec_code = code
89
+ if input_calls:
90
+ # Prep input override
91
+ vals = ",".join([f'"{v}"' for v in inputs])
92
+ stub = (
93
+ "import builtins\n"
94
+ "builtins._orig_input = builtins.input\n"
95
+ f"inputs = iter([{vals}])\n"
96
+ "builtins.input = lambda prompt='': next(inputs)\n"
97
+ )
98
+ exec_code = stub + exec_code
99
+ out, err, exc = execute_code(exec_code)
100
+ st.session_state.code_output = out
101
+ st.session_state.error_output = err or exc
102
 
103
+ # Show output / errors
104
+ if st.session_state.get("code_output"):
105
+ st.text_area("Output", st.session_state.code_output, height=120)
106
+ if st.session_state.get("error_output"):
107
+ st.error(st.session_state.error_output)
108
 
109
+ with col2:
110
+ st.subheader("Code Assistant")
111
+ render_chatbot(
112
+ code,
113
+ st.session_state.get("code_output", ""),
114
+ st.session_state.get("error_output", "")
115
+ )
 
 
 
 
 
 
 
 
116
 
117
+ # Footer
118
+ st.markdown(f"""
119
+ <div style='text-align:center; margin-top:1rem; color:{TEXT}66;'>
120
+ Built with ❤️ & Streamlit
121
+ </div>
122
+ """, unsafe_allow_html=True)