Spaces:
Sleeping
Sleeping
| import os | |
| import re | |
| import gradio as gr | |
| from langchain.prompts import PromptTemplate | |
| from langchain_openai import ChatOpenAI | |
| from langchain_chroma import Chroma | |
| from langchain_community.embeddings import HuggingFaceEmbeddings | |
| # Load embedding model and vector store from persisted DB | |
| embedding_model = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") | |
| vector_store = Chroma( | |
| embedding_function=embedding_model, | |
| persist_directory="geometry_db", # relative folder inside your Hugging Face Space | |
| collection_name="geometry_sol" | |
| ) | |
| # Load OpenAI key (set this in Hugging Face Space Secrets) | |
| os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY") | |
| # Load the LLM (GPT-3.5) | |
| llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.3) | |
| # Unified prompt to auto-detect intent | |
| template = PromptTemplate( | |
| input_variables=["context", "query"], | |
| template=""" | |
| You are a Virginia high school Geometry assistant. Based on the user question below, determine the correct response type and answer accordingly: | |
| User Question: | |
| {query} | |
| Based on the following SOL text: | |
| {context} | |
| Response Rules: | |
| - If the question is asking for an **SOL number**, respond with: | |
| 1. The exact SOL code (e.g., G.RLT.1) | |
| 2. The exact description line from the SOL guide | |
| ⚠️ Do not summarize. Only copy directly from the context. | |
| - If the user asks for a **lesson plan**, provide: | |
| - Simple explanation of the concept | |
| - Real-world example | |
| - Engaging class activity | |
| Format the output clearly with bullet points. | |
| - If the user asks for a **worksheet**, include: | |
| - Concept summary | |
| - A worked example | |
| - 3 practice problems | |
| Format the output clearly with bullet points. | |
| - If the user asks for **proofs**, include: | |
| - Student-friendly explanation | |
| - Real-world connection | |
| - One short class activity | |
| Format the output clearly with bullet points. | |
| - If the user asks for **flashcards**, generate 5 cards, each with: | |
| - A clear question | |
| - A short answer | |
| Format the output clearly with bullet points. | |
| Only answer one way depending on the intent of the question. | |
| """ | |
| ) | |
| # Optional: shortcut to solve simple math problems (like area of rectangle) | |
| def try_math_solver(query): | |
| match = re.search(r"rectangle.*l\s*=\s*(\d+).+w\s*=\s*(\d+)", query.lower()) | |
| if match: | |
| l, w = int(match.group(1)), int(match.group(2)) | |
| return f"The area of the rectangle is {l} × {w} = {l * w} square units." | |
| return None | |
| # RAG function using unified intent-aware prompt | |
| def rag_query(query): | |
| docs = vector_store.similarity_search(query, k=2) | |
| context = "\n\n".join([doc.page_content for doc in docs]) | |
| prompt = template.format_prompt(context=context, query=query).to_string() | |
| return llm.invoke(prompt).content | |
| # Gradio app function | |
| def ask_geometry_sol(query): | |
| math_result = try_math_solver(query) | |
| if math_result: | |
| return math_result | |
| try: | |
| return rag_query(query) | |
| except Exception as e: | |
| return f"⚠️ Error: {type(e).__name__} - {str(e)}" | |
| # Gradio UI (no need for manual response type selection anymore!) | |
| iface = gr.Interface( | |
| fn=ask_geometry_sol, | |
| inputs=gr.Textbox(label="Enter your Geometry SOL question or topic"), | |
| outputs="text", | |
| title="📘 Virginia Geometry SOL Assistant", | |
| description="Ask about any 2023 Geometry SOL (Standards of Learning). The assistant will auto-detect if you want a lesson plan, worksheet, proof, flashcards, or SOL reference." | |
| ) | |
| if __name__ == "__main__": | |
| iface.launch() |