| | import os |
| | import json |
| | from typing import List, Dict |
| |
|
| | import streamlit as st |
| | from streamlit_chat import message |
| | from langchain.chat_models import ChatOpenAI |
| | from langchain.chains import LLMChain |
| | from langchain.prompts import PromptTemplate |
| |
|
| | |
| | |
| | |
| | |
| | |
| | OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") |
| |
|
| | |
| | st.set_page_config(page_title="Socratic Learning Bot", page_icon="🤖", layout="centered") |
| |
|
| | |
| | if "conversation" not in st.session_state: |
| | st.session_state.conversation = None |
| | if "chat_history" not in st.session_state: |
| | st.session_state.chat_history = [] |
| | if "hint_level" not in st.session_state: |
| | st.session_state.hint_level = 1 |
| |
|
| |
|
| | |
| | @st.cache_resource |
| | def initialize_conversation(): |
| | llm = ChatOpenAI( |
| | temperature=0.7, |
| | openai_api_key=OPENAI_API_KEY, |
| | model_name="gpt-4" |
| | ) |
| |
|
| | template = """ |
| | You are an AI tutor designed to help users learn programming concepts and problem-solving skills using a Socratic method. Your primary goal is to guide users towards solutions by asking thought-provoking questions and encouraging critical thinking. Follow these guidelines when responding to user queries: |
| | |
| | 1. Begin with questions: |
| | a. Ask the user to explain their understanding of the problem. |
| | b. Inquire about their current approach or thought process. |
| | c. Encourage them to think about potential edge cases or limitations. |
| | |
| | 2. If the user provides code, help them identify issues: |
| | a. Ask them to walk through their code step-by-step. |
| | b. Point out specific lines that may contain errors or inefficiencies. |
| | c. Encourage the user to think about why those lines might be problematic. |
| | |
| | 3. Provide hints in the following stages, only moving to the next stage if the user is stuck: |
| | |
| | a. Hint 1: Ask a leading question about the topic or sub-topic that guides them towards the solution. |
| | b. Hint 2: Provide a conceptual hint framed as a question, encouraging them to make connections. |
| | c. Hint 3: Offer a more detailed explanation, but frame it as a series of questions for the user to consider. |
| | d. Hint 4: Present pseudocode as a series of questions (e.g., "What if we first...? Then how would we...?"). |
| | e. Hint 5: Provide a partial code skeleton with key parts missing, asking the user how they would fill in the gaps. |
| | f. Hint 6: As a last resort, provide a working solution, but ask the user to explain each part of the code. |
| | |
| | 4. Guide users through the problem-solving process from brute force to optimal solutions: |
| | a. Ask them to consider the simplest possible solution and its limitations. |
| | b. Encourage them to think about how they could improve upon their initial approach. |
| | c. Guide them towards optimization by asking about time and space complexity. |
| | |
| | 5. Continuously engage the user in the learning process: |
| | a. After each response from the user, ask follow-up questions to deepen their understanding. |
| | b. Encourage them to predict the outcome of their approach before testing it. |
| | c. If they seem confused, ask them to rephrase the problem or explain their current understanding. |
| | |
| | 6. Adaptively adjust your questioning: |
| | a. If the user is struggling, simplify your questions and provide more context. |
| | b. If the user is progressing well, ask more challenging questions to push their understanding further. |
| | |
| | 7. Before providing language-specific hints or code: |
| | a. Ask the user about their preferred programming language. |
| | b. Inquire about their familiarity with relevant language features or libraries. |
| | |
| | Remember, your role is to facilitate active learning. Avoid giving direct answers unless absolutely necessary. Always encourage users to arrive at solutions through their own reasoning and experimentation. |
| | |
| | Current hint level: {hint_level} |
| | Recent context: |
| | {context} |
| | |
| | Human: {human_input} |
| | AI Tutor: Let's approach this step-by-step. First, could you tell me more about... |
| | """ |
| |
|
| | prompt = PromptTemplate( |
| | input_variables=["context", "human_input", "hint_level"], |
| | template=template |
| | ) |
| |
|
| | return LLMChain(llm=llm, prompt=prompt) |
| |
|
| |
|
| | |
| | st.title("🤖 Socratic Learning Bot") |
| |
|
| |
|
| | |
| | def get_bot_response(user_input: str) -> str: |
| | if st.session_state.conversation is None: |
| | st.session_state.conversation = initialize_conversation() |
| |
|
| | |
| | recent_history = st.session_state.chat_history[-5:] |
| | context = "\n".join([f"{msg['role']}: {msg['content']}" for msg in recent_history]) |
| |
|
| | response = st.session_state.conversation.predict( |
| | context=context, |
| | human_input=user_input, |
| | hint_level=st.session_state.hint_level |
| | ) |
| | return response |
| |
|
| |
|
| | |
| | def display_chat_history(history: List[Dict[str, str]]): |
| | for i, chat in enumerate(history): |
| | if chat["role"] == "user": |
| | message(chat["content"], is_user=True, key=f"{i}_user") |
| | else: |
| | message(chat["content"], is_user=False, key=f"{i}_bot") |
| |
|
| |
|
| | |
| | def chat_interface(): |
| | |
| | if not st.session_state.chat_history: |
| | context = st.text_input("Please provide the programming topic or problem you'd like help with:") |
| | if context: |
| | bot_response = get_bot_response(f"The user wants help with the following topic or problem: {context}") |
| | st.session_state.chat_history.append({"role": "assistant", "content": bot_response}) |
| |
|
| | |
| | display_chat_history(st.session_state.chat_history) |
| |
|
| | |
| | user_input = st.text_input("Type your message here:", key="user_input") |
| |
|
| | |
| | col1, col2, col3 = st.columns(3) |
| | with col1: |
| | if st.button("Send"): |
| | if user_input: |
| | st.session_state.chat_history.append({"role": "user", "content": user_input}) |
| | bot_response = get_bot_response(user_input) |
| | st.session_state.chat_history.append({"role": "assistant", "content": bot_response}) |
| | st.rerun() |
| | with col2: |
| | if st.button("Next Hint"): |
| | st.session_state.hint_level = min(st.session_state.hint_level + 1, 6) |
| | bot_response = get_bot_response("I need more help. Can you provide the next hint?") |
| | st.session_state.chat_history.append({"role": "assistant", "content": bot_response}) |
| | st.rerun() |
| | with col3: |
| | if st.button("Reset Hints"): |
| | st.session_state.hint_level = 1 |
| | st.session_state.chat_history.append({"role": "system", "content": "Hint level has been reset to 1."}) |
| | st.rerun() |
| |
|
| |
|
| | if __name__ == "__main__": |
| | chat_interface() |