ak0601 commited on
Commit
cc0a162
·
verified ·
1 Parent(s): d17ee75

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -23
app.py CHANGED
@@ -1,3 +1,6 @@
 
 
 
1
  from fastapi import FastAPI, UploadFile, Form, HTTPException
2
  from pydantic import BaseModel
3
  import uvicorn
@@ -18,22 +21,35 @@ load_dotenv()
18
  client = OpenAI(api_key=os.getenv('DEEPSEEK_API_KEY'), base_url="https://api.deepseek.com",)
19
 
20
  # Initialize Gemini LLM
21
- # load_dotenv()
22
- # Google_key = os.getenv("GOOGLE_API_KEY")
23
- # print(str(Google_key))
24
  genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
25
  model = genai.GenerativeModel("gemini-2.0-flash")
 
 
 
26
  import firebase_admin
27
  from firebase_admin import credentials
28
  cred_dic = os.getenv("Firebase_cred")
29
 
 
 
30
  cred_dict = json.loads(cred_dic)
31
 
 
 
 
32
  cred = credentials.Certificate(cred_dict)
33
  firebase_admin.initialize_app(cred)
34
 
 
 
35
  app = FastAPI()
36
 
 
 
 
 
 
37
  app.add_middleware(
38
  CORSMiddleware,
39
  allow_origins=["*"],
@@ -42,22 +58,38 @@ app.add_middleware(
42
  allow_headers=["*"],
43
  )
44
  def generate_df():
45
- data = []
46
- db = firestore.client()
47
- docs = db.collection("test_results").get()
48
  for doc in docs:
49
- doc_data = doc.to_dict()
50
- doc_data['id'] = doc.id
51
- data.append(doc_data)
52
  df = pd.DataFrame(data)
53
  return df
54
 
55
  def generate_feedback(email, test_id):
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  df = generate_df()
57
- df_email = df[df['email'] == email]
58
- df_test_id = df_email[df_email['id'] == test_id]
59
- if not df_test_id.empty:
60
- response = df_test_id['responses'].values[0]
 
 
 
61
  feedback = model.generate_content(f"""You are an experienced tutor analyzing a student's test responses to provide constructive feedback. Below is the student's test history in JSON format. Your task is to:
62
 
63
  Identify Strengths: Highlight areas where the student performed well, demonstrating a strong understanding of the concepts.
@@ -68,10 +100,22 @@ Provide Actionable Suggestions: Offer specific advice on how the student can imp
68
 
69
  Encourage and Motivate: End with positive reinforcement to keep the student motivated.
70
  Test History:{str(response)} """)
71
- return feedback.text
72
  else:
73
  print("No test results found for this id")
74
  def generate_overall_feedback(email):
 
 
 
 
 
 
 
 
 
 
 
 
75
  df = generate_df()
76
  df_email = df[df['email'] == email]
77
  if not df_email.empty:
@@ -96,22 +140,49 @@ Test History:{str(response)} """)
96
 
97
  @app.post("/get_single_feedback")
98
  async def get_single_feedback(email: str, test_id: str):
 
 
 
 
 
 
 
99
  feedback = generate_feedback(email, test_id)
100
  return JSONResponse(content={"feedback": feedback})
101
 
102
  @app.post("/get_overall_feedback")
103
  async def get_overall_feedback(email: str):
104
- feedback = generate_overall_feedback(email)
 
 
 
 
 
 
105
  return JSONResponse(content={"feedback": feedback})
106
 
107
  @app.post("/get_strong_weak_topics")
108
- async def get_strong_weak_topics(email: str):
 
 
 
 
 
 
 
 
109
  df = generate_df()
110
  df_email = df[df['email'] == email]
 
 
111
  if len(df_email)<10:
 
 
 
112
  return JSONResponse(content={"message": "Please attempt atleast 10 tests to enable this feature"})
113
 
114
  elif len(df)>=10:
 
115
  response = df_email['responses'].values[:10]
116
  # Assuming response is a list of responses
117
  formatted_data = str(response) # Convert response to a string format suitable for the API call
@@ -148,7 +219,7 @@ async def get_strong_weak_topics(email: str):
148
  """
149
  }
150
  ],
151
- temperature=0.0
152
  )
153
 
154
  # Extract the JSON content from the completion object
@@ -160,13 +231,23 @@ async def get_strong_weak_topics(email: str):
160
 
161
  @app.post("/generate_flashcards")
162
  async def generate_flashcards(email: str):
163
- df = generate_df()
164
- df_email = df[df['email'] == email]
 
 
 
 
 
 
 
 
 
165
 
166
  if len(df_email) < 10:
167
- return JSONResponse(content={"message": "Please attempt at least 10 tests to enable flashcard generation."})
168
 
169
- # Step 1: Get the weak topics via DeepSeek
 
 
170
  response = df_email['responses'].values[:10]
171
  formatted_data = str(response)
172
 
@@ -206,7 +287,7 @@ async def generate_flashcards(email: str):
206
  if not weak_topics:
207
  return JSONResponse(content={"message": "Could not extract weak topics."})
208
 
209
- # Step 2: Generate flashcards using Gemini
210
  topic_str = ", ".join(weak_topics)
211
  flashcard_prompt = f"""Create 5 concise, simple, straightforward and distinct Anki cards to study the following topic, each with a front and back.
212
  Avoid repeating the content in the front on the back of the card. Avoid explicitly referring to the author or the article.
@@ -222,13 +303,22 @@ The topics: {topic_str}
222
  # Step 3: Parse Gemini response into JSON format
223
  flashcards_raw = flashcard_response.text.strip()
224
  flashcard_pattern = re.findall(r"Front:\s*(.*?)\nBack:\s*(.*?)(?=\nFront:|\Z)", flashcards_raw, re.DOTALL)
225
-
226
  flashcards = [{"Front": front.strip(), "Back": back.strip()} for front, back in flashcard_pattern]
227
 
228
  return JSONResponse(content=flashcards)
229
 
230
  @app.post("/generate_detailed_summary")
231
  async def generate_detailed_summary(email: str):
 
 
 
 
 
 
 
 
 
232
  df = generate_df()
233
  df_email = df[df['email'] == email]
234
 
 
1
+ # Import necessary libraries from FastAPI for creating the API, handling uploads, forms, and HTTP exceptions
2
+
3
+
4
  from fastapi import FastAPI, UploadFile, Form, HTTPException
5
  from pydantic import BaseModel
6
  import uvicorn
 
21
  client = OpenAI(api_key=os.getenv('DEEPSEEK_API_KEY'), base_url="https://api.deepseek.com",)
22
 
23
  # Initialize Gemini LLM
24
+
 
 
25
  genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
26
  model = genai.GenerativeModel("gemini-2.0-flash")
27
+
28
+ # Firebase Admin SDK Initialization
29
+ # Get the Firebase credentials (as a JSON string) from environment variables
30
  import firebase_admin
31
  from firebase_admin import credentials
32
  cred_dic = os.getenv("Firebase_cred")
33
 
34
+
35
+ # Parse the JSON string into a Python dictionary
36
  cred_dict = json.loads(cred_dic)
37
 
38
+
39
+ # Initialize the Firebase Admin app with the credentials
40
+ # This needs to be done only once
41
  cred = credentials.Certificate(cred_dict)
42
  firebase_admin.initialize_app(cred)
43
 
44
+
45
+ # Create an instance of the FastAPI application
46
  app = FastAPI()
47
 
48
+
49
+ # Add CORSMiddleware to the application
50
+ # This allows requests from any origin ("*"), supports credentials,
51
+ # allows all HTTP methods ("*"), and allows all headers ("*").
52
+ # Be cautious with "*" in production environments; specify origins if possible.
53
  app.add_middleware(
54
  CORSMiddleware,
55
  allow_origins=["*"],
 
58
  allow_headers=["*"],
59
  )
60
  def generate_df():
61
+ data = [] # Initialize an empty list to store document data
62
+ db = firestore.client() # Get a Firestore client instance
63
+ docs = db.collection("test_results").get()# Retrieve all documents from the "test_results" collection
64
  for doc in docs:
65
+ doc_data = doc.to_dict() # Convert Firestore document to a dictionary
66
+ doc_data['id'] = doc.id # Add the document ID to the dictionary
67
+ data.append(doc_data) # Append the document data to the list
68
  df = pd.DataFrame(data)
69
  return df
70
 
71
  def generate_feedback(email, test_id):
72
+
73
+ """
74
+ Generates feedback for a specific test taken by a student.
75
+ It filters the test results by email and test_id, then uses the Gemini model
76
+ to generate constructive feedback based on the student's responses for that test.
77
+
78
+ Args:
79
+ email (str): The email of the student.
80
+ test_id (str): The ID of the test.
81
+
82
+ Returns:
83
+ str: The generated feedback text, or None if no test results are found.
84
+ """
85
  df = generate_df()
86
+ df_email = df[df['email'] == email] # Get the DataFrame of all test results
87
+ df_test_id = df_email[df_email['id'] == test_id] # Filter by student's email
88
+ if not df_test_id.empty: # Check if any matching test result was found
89
+ response = df_test_id['responses'].values[0] # Get the 'responses' field from the first (and only) matching row
90
+ # Prepare the prompt for the Gemini model
91
+
92
+
93
  feedback = model.generate_content(f"""You are an experienced tutor analyzing a student's test responses to provide constructive feedback. Below is the student's test history in JSON format. Your task is to:
94
 
95
  Identify Strengths: Highlight areas where the student performed well, demonstrating a strong understanding of the concepts.
 
100
 
101
  Encourage and Motivate: End with positive reinforcement to keep the student motivated.
102
  Test History:{str(response)} """)
103
+ return feedback.text # Return the text part of the response
104
  else:
105
  print("No test results found for this id")
106
  def generate_overall_feedback(email):
107
+ """
108
+ Generates overall feedback for a student based on all their test results.
109
+ It filters test results by email and uses the Gemini model to provide
110
+ a holistic view of the student's performance.
111
+
112
+ Args:
113
+ email (str): The email of the student.
114
+
115
+ Returns:
116
+ str: The generated overall feedback text, or None if no test results are found.
117
+ """
118
+
119
  df = generate_df()
120
  df_email = df[df['email'] == email]
121
  if not df_email.empty:
 
140
 
141
  @app.post("/get_single_feedback")
142
  async def get_single_feedback(email: str, test_id: str):
143
+
144
+ """
145
+ API endpoint to get feedback for a single test.
146
+ Expects 'email' and 'test_id' as form data.
147
+ """
148
+
149
+
150
  feedback = generate_feedback(email, test_id)
151
  return JSONResponse(content={"feedback": feedback})
152
 
153
  @app.post("/get_overall_feedback")
154
  async def get_overall_feedback(email: str):
155
+
156
+ """
157
+ API endpoint to get overall feedback for a student.
158
+ Expects 'email' as form data.
159
+ """
160
+
161
+ feedback = generate_overall_feedback(email) # Call the helper function to generate overall feedback
162
  return JSONResponse(content={"feedback": feedback})
163
 
164
  @app.post("/get_strong_weak_topics")
165
+ async def get_strong_weak_topics(email: str):
166
+
167
+ """
168
+ API endpoint to identify strong and weak topics for a student.
169
+ Requires at least 10 test attempts. Uses DeepSeek API for analysis.
170
+ Expects 'email' as form data.
171
+ """
172
+
173
+
174
  df = generate_df()
175
  df_email = df[df['email'] == email]
176
+
177
+ # Check if the student has attempted at least 10 tests
178
  if len(df_email)<10:
179
+
180
+ # The original condition was `len(df)>=10`, which seems to check the total number of tests in the DB,
181
+ # not for the specific user. Changed to `len(df_email) >= 10`.
182
  return JSONResponse(content={"message": "Please attempt atleast 10 tests to enable this feature"})
183
 
184
  elif len(df)>=10:
185
+ # Get responses from the latest 10 tests (or all if fewer than 10, but the check above ensures at least 10)
186
  response = df_email['responses'].values[:10]
187
  # Assuming response is a list of responses
188
  formatted_data = str(response) # Convert response to a string format suitable for the API call
 
219
  """
220
  }
221
  ],
222
+ temperature=0.0 # Set temperature to 0 for deterministic output
223
  )
224
 
225
  # Extract the JSON content from the completion object
 
231
 
232
  @app.post("/generate_flashcards")
233
  async def generate_flashcards(email: str):
234
+
235
+ """
236
+ API endpoint to generate flashcards for a student's weak topics.
237
+ Requires at least 10 test attempts.
238
+ First, it identifies weak topics using DeepSeek.
239
+ Then, it generates flashcards for these topics using Gemini.
240
+ Expects 'email' as form data.
241
+ """
242
+
243
+ df = generate_df() # Get all test results
244
+ df_email = df[df['email'] == email]
245
 
246
  if len(df_email) < 10:
 
247
 
248
+ return JSONResponse(content={"message": "Please attempt at least 10 tests to enable flashcard generation."})
249
+ # Step 1: Get the weak topics via DeepSeek
250
+ # Get responses from the latest 10 tests
251
  response = df_email['responses'].values[:10]
252
  formatted_data = str(response)
253
 
 
287
  if not weak_topics:
288
  return JSONResponse(content={"message": "Could not extract weak topics."})
289
 
290
+ # Step 2: Generate flashcards using Gemini for the identified weak topics
291
  topic_str = ", ".join(weak_topics)
292
  flashcard_prompt = f"""Create 5 concise, simple, straightforward and distinct Anki cards to study the following topic, each with a front and back.
293
  Avoid repeating the content in the front on the back of the card. Avoid explicitly referring to the author or the article.
 
303
  # Step 3: Parse Gemini response into JSON format
304
  flashcards_raw = flashcard_response.text.strip()
305
  flashcard_pattern = re.findall(r"Front:\s*(.*?)\nBack:\s*(.*?)(?=\nFront:|\Z)", flashcards_raw, re.DOTALL)
306
+ # Use regex to find all "Front:" and "Back:" pairs
307
  flashcards = [{"Front": front.strip(), "Back": back.strip()} for front, back in flashcard_pattern]
308
 
309
  return JSONResponse(content=flashcards)
310
 
311
  @app.post("/generate_detailed_summary")
312
  async def generate_detailed_summary(email: str):
313
+ """
314
+ API endpoint to generate detailed summaries for a student's weak topics.
315
+ Requires at least 10 test attempts.
316
+ First, it identifies weak topics using DeepSeek.
317
+ Then, it generates summaries for these topics using Gemini.
318
+ Expects 'email' as form data.
319
+ """
320
+
321
+
322
  df = generate_df()
323
  df_email = df[df['email'] == email]
324