-
Notifications
You must be signed in to change notification settings - Fork 317
Description
Prerequisites
- Write a descriptive title.
- Make sure you are able to repro it on the latest released version
- Search the existing issues, especially the pinned issues.
Exception report
the error is:
[DEBUG ] [https ]//api.deepseek.com:443 "POST /v1/chat/completions HTTP/1.1" 401 153
API Error 401: {"error":{"message":"Authentication Fails, Your api key: ****here is invalid","type":"authentication_error","param":null,"code":"invalid_request_error"}}Screenshot
I used an API for OpenAI, but I'm unable to use Qwen and Deepseek, and always the error related to authentication 401.
Environment data
VScode using python and kivySteps to reproduce
asking for responses or generating a plan after getting students'' constraints from the database, and university constraints are written in the prompt.
class AcademicPlanScreen(Screen):
def get_student_constraints(self):
"""Retrieve student academic data from database and return as constraints dictionary."""
try:
home_screen = self.manager.get_screen('HomeScreen')
student_id = home_screen.student_id
with create_connection() as conn:
with conn.cursor() as cur:
if not self._student_exists(cur, student_id):
show_error_popup("Student record not found in database")
return None
student_data = self._fetch_student_data(cur, student_id)
if not student_data:
show_error_popup("No student data available")
return None
return {
'gpa': float(student_data[0]),
'completed_hours': int(student_data[1]),
'completed_courses': student_data[2] if isinstance(student_data[2], list) else [],
'current_semester': "Fall 2025", # Default starting semester
'semesters_per_year': int(student_data[3]),
'fees_per_semester': student_data[4],
'preferences': student_data[5] or "Standard"
}
except Exception as e:
error_msg = f"Error fetching student constraints: {str(e)}"
print(error_msg)
show_error_popup(error_msg)
return None
def _student_exists(self, cursor, student_id):
"""Check if student exists in database."""
try:
cursor.execute("SELECT 1 FROM students WHERE id = %s", (student_id,))
return cursor.fetchone() is not None
except Exception as e:
print(f"Error checking student existence: {str(e)}")
return False
def _fetch_student_data(self, cursor, student_id):
"""Fetch student academic data from database."""
try:
cursor.execute("""
SELECT gpa, completed_hours, completed_courses,
semester, fees, preferences
FROM students
WHERE id = %s
""", (student_id,))
return cursor.fetchone()
except Exception as e:
print(f"Error fetching student data: {str(e)}")
return None
def validate_student_data(self, student_data):
"""
Validate student data before generating plan.
Returns tuple: (is_valid: bool, validation_msg: str)
"""
if not isinstance(student_data, dict):
return False, "Invalid student data format"
required_fields = ['gpa', 'completed_hours', 'completed_courses',
'current_semester', 'semesters_per_year',
'fees_per_semester', 'preferences']
for field in required_fields:
if field not in student_data:
return False, f"Missing required field: {field}"
# Type checks
if not isinstance(student_data['completed_courses'], list):
return False, "Completed courses should be a list"
# Value range checks
if not (0 <= student_data['gpa'] <= 4):
return False, "GPA must be between 0 and 4"
if student_data['completed_hours'] < 0:
return False, "Completed hours cannot be negative"
return True, "Validation passed"
def _build_prompt(self, student_data):
"""Construct the prompt for AI plan generation with better formatting."""
try:
# Format completed courses as a bulleted list
completed_courses_str = "\n".join(f"- {course}" for course in student_data['completed_courses']) \
if student_data['completed_courses'] else "None"
return f"""
You are an expert academic advisor at AOU Bahrain. Create a semester-by-semester academic plan.
STUDENT PROFILE:
- Current Semester: {student_data['current_semester']}
- GPA: {student_data['gpa']:.2f}
- Completed Hours: {student_data['completed_hours']}
- Completed Courses:
{completed_courses_str} - Learning Style: {student_data['preferences']}
- Semesters Per Year: {student_data['semesters_per_year']}
- Fees Per Semester: {student_data['fees_per_semester']}
UNIVERSITY REQUIREMENTS:
- Total required hours to graduate: 131
- Must complete all prerequisites before taking advanced courses
- Maximum course load per semester: 18 hours
- Minimum course load per semester: 12 hours
PREREQUISITES:
[Your existing prerequisite list here]
Generate a detailed 4-year plan with:
- Semester-by-semester course lists
- Credit hours per semester
- Prerequisite verification
- Balanced workload
- Estimated fees
- Clear rationale for each semester's course selection
Format the plan as:
Semester [Number] ([Season] [Year])
Rationale: [Explanation]
| Course Code | Credit Hours | Fees |
|---|---|---|
| [Course list] | ||
| Total Hours: X | ||
| Estimated Fees: Y BD | ||
| """ |
except Exception as e:
print(f"Error building prompt: {str(e)}")
return ""
def _generate_ai_plan(self, prompt):
"""Generate plan with better error handling and retries."""
try:
# Get API key from environment (recommended) or config
api_key = os.getenv("DEEPSEEK_API_KEY") or "your_api_key_here"
if not api_key:
return "API key not configured"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
payload = {
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "You are an expert academic advisor."},
{"role": "user", "content": prompt}
],
"temperature": 0.3,
"max_tokens": 2000
}
for attempt in range(3):
try:
response = requests.post(
"https://api.deepseek.com/v1/chat/completions",
headers=headers,
json=payload,
timeout=30
)
if response.status_code == 200:
result = response.json()
return result.get("choices", [{}])[0].get("message", {}).get("content", "No content returned")
else:
print(f"API Error {response.status_code}: {response.text}")
time.sleep(2 ** attempt) # Exponential backoff
except Exception as e:
print(f"Attempt {attempt + 1} failed: {str(e)}")
time.sleep(2 ** attempt)
return "Failed to generate plan after multiple attempts. Please try again later."
except Exception as e:
print(f"Error in plan generation: {str(e)}")
return f"Error generating plan: {str(e)}"
def generate_plan(self):
"""Orchestrate the plan generation process."""
try:
# Get student data
student_data = self.get_student_constraints()
if not student_data:
show_error_popup("Failed to get student data")
return
# Validate data
is_valid, msg = self.validate_student_data(student_data)
if not is_valid:
show_error_popup(f"Invalid data: {msg}")
return
# Build and send prompt
prompt = self._build_prompt(student_data)
if not prompt:
show_error_popup("Failed to create prompt")
return
# Generate plan
plan = self._generate_ai_plan(prompt)
# Display results
if plan and not plan.startswith("Error") and not plan.startswith("Failed"):
self._display_plan(plan)
else:
show_error_popup(plan or "Empty plan generated")
except Exception as e:
show_error_popup(f"Unexpected error: {str(e)}")
Expected behavior
Getting a generated plan considering students and university constraints.
Actual behavior
[DEBUG ] [https ]//api.deepseek.com:443 "POST /v1/chat/completions HTTP/1.1" 401 153
API Error 401: {"error":{"message":"Authentication Fails, Your api key: ****here is invalid","type":"authentication_error","param":null,"code":"invalid_request_error"}}