File size: 5,703 Bytes
72a3c35
 
573a91c
72a3c35
 
 
 
 
b1d7b45
573a91c
b1de38a
72a3c35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9e30f97
 
72a3c35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54cc619
 
 
72a3c35
54cc619
 
72a3c35
54cc619
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b3bf22a
 
 
 
 
 
 
 
 
 
 
 
 
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
# app.py
import gradio as gr
import os
from transformers import pipeline
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
import json
import re


# --- Load necessary components for the RAG system ---
# These paths are relative to the Space's root directory
FAISS_INDEX_PATH = "sol_faiss_index.bin"
DOCUMENT_IDS_PATH = "sol_document_ids.json"

# Load SentenceTransformer model
# Ensure this model is downloaded or available in the environment
# For Spaces, you might need to add it to requirements.txt or directly download if space has internet
# It's better to declare it globally or as a shared resource.
try:
    model = SentenceTransformer('all-mpnet-base-v2')
except Exception as e:
    print(f"Error loading SentenceTransformer model: {e}")
    print("Attempting to load from local cache or download on first use.")
    # If running in a Space, the model will be downloaded to cache if not present.
    # Ensure you have internet access in your Space settings.

# Load FAISS index
try:
    index = faiss.read_index(FAISS_INDEX_PATH)
except Exception as e:
    print(f"Error loading FAISS index: {e}")
    # Handle error, maybe create a dummy index or exit
    index = None # Placeholder if loading fails

# Load document IDs
try:
    with open(DOCUMENT_IDS_PATH, "r") as f:
        document_ids = json.load(f)
except Exception as e:
    print(f"Error loading document IDs: {e}")
    document_ids = [] # Placeholder if loading fails

# Placeholder for the actual content of "10 Geometry Mathematics Instructional Guide.pdf"
# In a real deployed scenario, this content would be loaded from a file
# that you upload to your Hugging Face Space or fetched at runtime.
# For now, we'll assume it's available or that 'documents' are pre-processed and loaded.
# You would typically load the 'documents' list created in Step 2 here.
# For deployment, it's best to save the `documents` list (sol_data) as a JSON
# and load it back. Let's add that.

# Assuming you've saved sol_data as 'sol_documents.json'
SOL_DOCUMENTS_PATH = "sol_documents.json"
try:
    with open(SOL_DOCUMENTS_PATH, "r") as f:
        documents = json.load(f)
except Exception as e:
    print(f"Error loading sol documents: {e}")
    documents = [] # Placeholder

# Load LLM for generation
# For a Hugging Face Space, you need to ensure the model is available.
# 'google/gemma-2b-it' is a good option.
# Ensure you set up environment variables or secrets for API keys if using paid models.
try:
   # llm_pipeline = pipeline("text-generation", model="TinyLlama/TinyLlama-1.1B-Chat-v1.0")
    llm_pipeline = pipeline("text-generation", model="google/gemma-2b-it")
except Exception as e:
    print(f"Error loading LLM pipeline: {e}")
    llm_pipeline = None # Placeholder


def retrieve_and_generate_app(query, top_k=3):
    if not model or not index or not document_ids or not documents or not llm_pipeline:
        return "System not fully initialized. Please check logs for missing components."

    # 1. Query Embedding
    query_embedding = model.encode([query])

    # 2. Retrieval using FAISS
    D, I = index.search(query_embedding, top_k)

    retrieved_docs = []
    for i in I[0]:
        sol_id = document_ids[i]
        # Find the full content of the retrieved SOL
        # This relies on the 'documents' list being correctly loaded and matching by ID
        # --- CHANGE 1: Use 'text' key instead of 'content' here ---
        retrieved_content = next((doc["text"] for doc in documents if doc["id"] == sol_id), "Content not found.")
        retrieved_docs.append({"id": sol_id, "content": retrieved_content}) # Keep 'content' here for consistency in retrieved_docs structure if you like

    # --- CHANGE 2: Use 'text' key here for building the context ---
    context = "\n\n".join([f"SOL {doc['id']}: {doc['text']}" for doc in retrieved_docs])

    # --- CHANGE 3: Complete the prompt string ---
    prompt = f"""
Given the following information about Virginia Standards of Learning (SOLs):

{context}

Based on this information, answer the following question:
{query}

If the question is about a specific SOL number, provide a direct explanation for that SOL.
If asked for lesson plans, worksheets, or proofs, explain what the document generally entails and whether it provides such materials.
Be concise and to the point.
"""
    # --- Start of the print statements for debugging (keep these for now!) ---
    print(f"\n--- PROMPT SENT TO LLM ---\n{prompt}\n--------------------------\n")

    response = llm_pipeline(prompt, max_new_tokens=500, num_return_sequences=1, do_sample=True, temperature=0.7)

    generated_text = response[0]['generated_text']

    print(f"\n--- RAW GENERATED TEXT ---\n{generated_text}\n--------------------------\n")

    answer_start_marker = f"Based on this information, answer the following question:\n{query}"
    if answer_start_marker in generated_text:
        answer = generated_text.split(answer_start_marker, 1)[1].strip()
        answer = re.sub(r'If the question is about a specific SOL number,.*?$', '', answer, flags=re.DOTALL).strip()
    else:
        answer = generated_text

    print(f"\n--- FINAL ANSWER ---\n{answer}\n--------------------\n")
    # --- End of the print statements for debugging ---

    return answer

    # Create Gradio interface
demo = gr.Interface(
    fn=retrieve_and_generate_app,
    inputs=gr.Textbox(lines=2, placeholder="Enter your geometry-related question here..."),
    outputs=gr.Textbox(label="Generated Answer"),
    title="Virginia SOL Geometry Assistant",
    description="Ask questions about the Geometry SOL Instructional Guide"
)

# Launch the app
if __name__ == "__main__":
    demo.launch()