Spaces:
Running
Running
import streamlit as st | |
from groq import Groq | |
import requests | |
# ======================= | |
# API Clients Initialization | |
# ======================= | |
groq_client = None | |
groq_status = "โ" | |
if "GROQ_API_KEY" in st.secrets: | |
try: | |
groq_client = Groq(api_key=st.secrets["GROQ_API_KEY"]) | |
groq_client.models.list() # test | |
groq_status = "โ " | |
except Exception: | |
groq_client = None | |
groq_status = "โ" | |
huggingface_api_key = st.secrets.get("HF_API_KEY", None) | |
hf_status = "โ" | |
if huggingface_api_key: | |
try: | |
headers = {"Authorization": f"Bearer {huggingface_api_key}"} | |
response = requests.get("https://api-inference.huggingface.co/status", headers=headers) | |
if response.status_code in [200, 401, 403]: | |
hf_status = "โ " | |
except Exception: | |
hf_status = "โ" | |
# ======================= | |
# Session State | |
# ======================= | |
if "projects" not in st.session_state: | |
st.session_state.projects = {"Default Chat": {"tab": "generate", "history": []}} | |
if "active_project" not in st.session_state: | |
st.session_state.active_project = "Default Chat" | |
# ======================= | |
# Sidebar Project Manager | |
# ======================= | |
st.sidebar.title("๐ Chats / Projects") | |
# Sidebar only scrolls when hovered | |
st.markdown( | |
""" | |
<style> | |
[data-testid="stSidebar"] { | |
overflow-y: hidden !important; /* No scroll by default */ | |
height: 100vh !important; | |
} | |
[data-testid="stSidebar"]:hover { | |
overflow-y: auto !important; /* Scroll only when hovered */ | |
} | |
</style> | |
""", | |
unsafe_allow_html=True | |
) | |
with st.sidebar: | |
for project_name in list(st.session_state.projects.keys()): | |
cols = st.columns([4, 1]) | |
with cols[0]: | |
if st.button(project_name, use_container_width=True): | |
st.session_state.active_project = project_name | |
with cols[1]: | |
with st.popover("โฎ"): | |
new_name = st.text_input("Rename", value=project_name, key=f"rename_{project_name}") | |
if st.button("Save", key=f"save_{project_name}"): | |
if new_name and new_name != project_name: | |
st.session_state.projects[new_name] = st.session_state.projects.pop(project_name) | |
if st.session_state.active_project == project_name: | |
st.session_state.active_project = new_name | |
st.rerun() | |
if st.button("Delete", key=f"delete_{project_name}"): | |
if project_name in st.session_state.projects and len(st.session_state.projects) > 1: | |
st.session_state.projects.pop(project_name) | |
st.session_state.active_project = list(st.session_state.projects.keys())[0] | |
st.rerun() | |
if st.button("โ New Chat"): | |
new_name = f"Chat {len(st.session_state.projects) + 1}" | |
st.session_state.projects[new_name] = {"tab": "generate", "history": []} | |
st.session_state.active_project = new_name | |
st.rerun() | |
# ======================= | |
# Sidebar API Settings | |
# ======================= | |
st.sidebar.markdown("---") | |
st.sidebar.title("โ๏ธ Settings") | |
st.sidebar.markdown(f"**Groq API Status:** {groq_status}") | |
st.sidebar.markdown(f"**HuggingFace API Status:** {hf_status}") | |
api_priority = st.sidebar.radio( | |
"Choose API Priority", | |
["Groq First", "HuggingFace First"], | |
index=0 | |
) | |
model_choice = st.sidebar.selectbox( | |
"Choose Model", | |
["llama-3.1-8b-instant", "llama-3.1-70b-versatile", "mixtral-8x7b-32768"] | |
) | |
# ======================= | |
# Helper Functions | |
# ======================= | |
def call_groq(system_prompt, chat_history): | |
if not groq_client: | |
return None | |
try: | |
response = groq_client.chat.completions.create( | |
model=model_choice, | |
messages=[{"role": "system", "content": system_prompt}] | |
+ [{"role": role, "content": msg} for role, msg in chat_history], | |
temperature=0.4 | |
) | |
return response.choices[0].message.content | |
except Exception as e: | |
st.warning(f"โ ๏ธ Groq API error: {e}") | |
return None | |
def call_huggingface(system_prompt, chat_history): | |
if not huggingface_api_key: | |
return None | |
try: | |
headers = {"Authorization": f"Bearer {huggingface_api_key}"} | |
payload = { | |
"inputs": "\n".join([msg for _, msg in chat_history]), | |
"parameters": {"temperature": 0.5, "max_new_tokens": 500} | |
} | |
response = requests.post( | |
f"https://api-inference.huggingface.co/models/{model_choice}", | |
headers=headers, | |
json=payload | |
) | |
if response.status_code == 200: | |
data = response.json() | |
if isinstance(data, list) and "generated_text" in data[0]: | |
return data[0]["generated_text"] | |
return str(data) | |
else: | |
st.warning(f"โ ๏ธ Hugging Face error: {response.text}") | |
return None | |
except Exception as e: | |
st.warning(f"โ ๏ธ Hugging Face exception: {e}") | |
return None | |
def get_ai_response(system_prompt, chat_history): | |
if api_priority == "Groq First": | |
ai_msg = call_groq(system_prompt, chat_history) | |
if ai_msg is None: | |
ai_msg = call_huggingface(system_prompt, chat_history) | |
else: | |
ai_msg = call_huggingface(system_prompt, chat_history) | |
if ai_msg is None: | |
ai_msg = call_groq(system_prompt, chat_history) | |
return ai_msg or "โ Both APIs failed. Please check your API keys or try again later." | |
# ======================= | |
# Main Title | |
# ======================= | |
st.title("๐ค CodeCraft AI - Mini Copilot (Chat Edition)") | |
st.write("") # Empty line after title | |
# ======================= | |
# Chat UI | |
# ======================= | |
def chat_ui(tab_name, system_prompt, input_key): | |
project = st.session_state.projects[st.session_state.active_project] | |
chat_history = project["history"] | |
st.subheader(f"{tab_name} ({st.session_state.active_project})") | |
chat_container = st.container() | |
with chat_container: | |
for role, msg in chat_history: | |
with st.chat_message(role): | |
if role == "assistant" and "```" in msg: | |
parts = msg.split("```") | |
for i, part in enumerate(parts): | |
if i % 2 == 1: | |
lang, *code_lines = part.split("\n") | |
code = "\n".join(code_lines) | |
st.code(code, language=lang if lang else "python") | |
else: | |
st.write(part) | |
else: | |
st.write(msg) | |
user_input = st.chat_input("Type your message...", key=input_key) | |
if user_input: | |
chat_history.append(("user", user_input)) | |
with st.spinner("๐ค Thinking..."): | |
ai_msg = get_ai_response(system_prompt, chat_history) | |
chat_history.append(("assistant", ai_msg)) | |
st.rerun() | |
# ======================= | |
# Tabs | |
# ======================= | |
tab1, tab2, tab3 = st.tabs(["๐ก Generate Code", "๐ Debug Code", "๐ Explain Code"]) | |
with tab1: | |
chat_ui("๐ก Generate Code", | |
"You are a helpful coding assistant. Generate correct code first, then a short simple explanation.", | |
"generate_input") | |
with tab2: | |
chat_ui("๐ Debug Code", | |
"You are an expert code debugger. Fix errors and give corrected code, then explain what changed and why.", | |
"debug_input") | |
with tab3: | |
chat_ui("๐ Explain Code", | |
"You are a teacher that explains code in simple words. The user pastes code, and you explain step by step.", | |
"explain_input") | |
# ======================= | |
# Footer | |
# ======================= | |
st.markdown("---") | |
st.caption("โจ CodeCraft may make mistakes. Always check important info.") | |