Skip to content

Gemini#19

Merged
ndayiemile merged 5 commits intomainfrom
gemini
Sep 22, 2025
Merged

Gemini#19
ndayiemile merged 5 commits intomainfrom
gemini

Conversation

@Shen0000
Copy link
Collaborator

@Shen0000 Shen0000 commented Sep 21, 2025

Removed HuggingFace implementation including related files, keeping Gemini implementation

Description by Korbit AI

What change is being made?

Replace retrieval-based RAG flow with a Gemini-powered resume analysis workflow, introduce a new enhanced GeminiResumeAnalyzer for structured, context-aware resume feedback, and align related backend/admin/views templates and settings accordingly.

Why are these changes being made?

Adopt Gemini-native capabilities for more consistent, structured responses and streamlined context handling; remove legacy retrieval-based switches and external token dependencies to simplify configuration and improve UX (including improved password management and related UI routes).

Is this description stale? Ask me to generate a new description by commenting /korbit-generate-pr-description

Copy link

@korbit-ai korbit-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by Korbit AI

Korbit automatically attempts to detect when you fix issues in new commits.
Category Issue Status
Security Insecure password reset token format ▹ view
Documentation Missing Password Requirements ▹ view
Readability Missing Form Labels ▹ view
Readability All Caps Button Text ▹ view
Security Insecure API Key Storage ▹ view
Security Unsafe file path construction ▹ view
Functionality Hardcoded PDF MIME type assumption ▹ view
Error Handling Unvalidated conversation history structure ▹ view
Design Missing Dependency Injection ▹ view
Readability Unexplained Configuration Values ▹ view
Files scanned
File Path Reviewed
resumax_backend/resumax_algo/admin.py
resumax_backend/resumax_auth/urls.py
resumax_backend/resumax_auth/templates/change_password.html
resumax_backend/resumax_backend/settings.py
resumax_backend/resumax_algo/templates/resumax_algo/index.html
resumax_backend/resumax_api/views.py
enhanced_gemini_rag_example.py
resumax_backend/resumax_auth/views.py

Explore our documentation to understand the languages and file types we support and the files we ignore.

Check out our docs on how you can make Korbit work best for you and your team.

Loving Korbit!? Share us on LinkedIn Reddit and X

Comment on lines +9 to +10
path('password-reset-sent/<str:reset_id>/', views.PasswordResetSent, name='password-reset-sent'),
path('reset-password/<str:reset_id>/', views.ResetPassword, name='reset-password'),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Insecure password reset token format category Security

Tell me more
What is the issue?

The reset_id parameter uses str:reset_id type which accepts any string value, potentially allowing unauthorized access to password reset pages with guessable or enumerable IDs.

Why this matters

Using simple string IDs for password reset tokens creates security vulnerabilities where attackers could potentially guess or enumerate valid reset IDs, leading to unauthorized password resets.

Suggested change ∙ Feature Preview

Use UUID format for reset_id to ensure cryptographically secure, non-guessable tokens:

path('password-reset-sent/<uuid:reset_id>/', views.PasswordResetSent, name='password-reset-sent'),
path('reset-password/<uuid:reset_id>/', views.ResetPassword, name='reset-password'),
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

</div>

<div class="input-field">
<input type="password" name="new_password" required placeholder="New Password"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Password Requirements category Documentation

Tell me more
What is the issue?

Missing password requirements or constraints information for users

Why this matters

Users may create passwords that don't meet system requirements, leading to failed submissions and frustration

Suggested change ∙ Feature Preview
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

</div>

<div class="submit-btn-container">
<input type="submit" value="CHANGE PASSWORD" />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All Caps Button Text category Readability

Tell me more
What is the issue?

The submit button text is in all caps, which reduces readability and doesn't follow standard UI text conventions.

Why this matters

All caps text is harder to read and scan quickly, and is often interpreted as 'shouting' in UI design. Title case or sentence case is more appropriate for button text.

Suggested change ∙ Feature Preview
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +22 to +24
<div class="input-field">
<input type="password" name="current_password" required placeholder="Current Password"/>
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Form Labels category Readability

Tell me more
What is the issue?

Password input fields lack labels, relying only on placeholders which disappear when typing, making the form less accessible and harder to understand.

Why this matters

Placeholders alone are poor substitutes for labels as they vanish during input, forcing users to remember what each field is for. This impacts both usability and accessibility.

Suggested change ∙ Feature Preview
Current Password
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

"""
Enhanced response generation that replaces both HuggingFace RAG and basic Gemini
"""
analyzer = GeminiResumeAnalyzer(api_key=settings.GEMINI_API_KEY)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Insecure API Key Storage category Security

Tell me more
What is the issue?

The API key is being directly accessed from a settings file, which may not be the most secure method for handling sensitive credentials.

Why this matters

Storing API keys in configuration files can lead to accidental exposure if the file is compromised or inadvertently shared. This increases the risk of unauthorized access to the Gemini API.

Suggested change ∙ Feature Preview

Use environment variables or a secure secret management system to store and retrieve the API key. For example:

import os

api_key = os.environ.get('GEMINI_API_KEY')
analyzer = GeminiResumeAnalyzer(api_key=api_key)
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

# Convert file URLs to file paths
file_paths = []
if file_urls:
file_paths = [pathlib.Path(str(settings.BASE_DIR) + url) for url in file_urls]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsafe file path construction category Security

Tell me more
What is the issue?

String concatenation for file paths can create invalid paths and doesn't handle path separators correctly across operating systems.

Why this matters

This could result in malformed file paths that don't exist, causing file reading failures and potential security vulnerabilities from path traversal.

Suggested change ∙ Feature Preview

Use proper path joining methods:

file_paths = [pathlib.Path(settings.BASE_DIR) / url.lstrip('/') for url in file_urls]

Or:

file_paths = [pathlib.Path(settings.BASE_DIR).joinpath(url.lstrip('/')) for url in file_urls]
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

for file_path in resume_files:
file_content = await self._read_file_async(file_path)
file_parts.append(
types.Part.from_bytes(data=file_content, mime_type='application/pdf')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded PDF MIME type assumption category Functionality

Tell me more
What is the issue?

The code hardcodes MIME type as 'application/pdf' for all files, but doesn't validate that the files are actually PDFs.

Why this matters

This will cause API errors or incorrect processing when non-PDF files are uploaded, leading to failed resume analysis requests.

Suggested change ∙ Feature Preview

Add MIME type detection or validation:

import mimetypes

# In the file processing loop:
mime_type, _ = mimetypes.guess_type(str(file_path))
if not mime_type:
    mime_type = 'application/octet-stream'
file_parts.append(
    types.Part.from_bytes(data=file_content, mime_type=mime_type)
)
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +82 to +83
for conv in conversation_history[-3:]: # Last 3 conversations for context
context += f"User: {conv.prompt}\nAssistant: {conv.response[:200]}...\n\n"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unvalidated conversation history structure category Error Handling

Tell me more
What is the issue?

The code assumes conversation_history items have 'prompt' and 'response' attributes without validation, which will cause AttributeError if the structure is different.

Why this matters

This will crash the application when conversation history objects don't match the expected structure, breaking the context-building functionality.

Suggested change ∙ Feature Preview

Add attribute validation:

for conv in conversation_history[-3:]:
    if hasattr(conv, 'prompt') and hasattr(conv, 'response'):
        context += f"User: {conv.prompt}\nAssistant: {conv.response[:200]}...\n\n"
    else:
        # Handle dict-like objects or log warning
        prompt = getattr(conv, 'prompt', conv.get('prompt', 'Unknown'))
        response = getattr(conv, 'response', conv.get('response', 'Unknown'))
        context += f"User: {prompt}\nAssistant: {response[:200]}...\n\n"
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +7 to +9
class GeminiResumeAnalyzer:
def __init__(self, api_key):
self.client = genai.Client(api_key=api_key)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Dependency Injection category Design

Tell me more
What is the issue?

The class directly instantiates its dependency (genai.Client) rather than following dependency injection principles.

Why this matters

This tight coupling makes the class harder to test and less flexible for future changes or different implementations.

Suggested change ∙ Feature Preview
class GeminiResumeAnalyzer:
    def __init__(self, client):
        self.client = client

# Usage
client = genai.Client(api_key=api_key)
analyzer = GeminiResumeAnalyzer(client)
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

Comment on lines +65 to +71
model="gemini-1.5-flash",
contents=content_parts,
generation_config={
"temperature": 0.3, # More consistent responses
"top_p": 0.8,
"max_output_tokens": 2048,
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unexplained Configuration Values category Readability

Tell me more
What is the issue?

Magic numbers are used in the generation configuration without clear explanation of their significance or impact.

Why this matters

Future developers will have difficulty understanding why these specific values were chosen and when they should be adjusted.

Suggested change ∙ Feature Preview

Extract these values as class constants with descriptive names and add comments explaining their purpose:

class GeminiResumeAnalyzer:
    # Lower temperature (0-1) for more focused, deterministic outputs
    TEMPERATURE = 0.3
    # Nucleus sampling parameter (0-1) controlling response diversity
    TOP_P = 0.8
    # Maximum length of generated response in tokens
    MAX_OUTPUT_TOKENS = 2048
    
    ...
    
    generation_config={
        "temperature": self.TEMPERATURE,
        "top_p": self.TOP_P,
        "max_output_tokens": self.MAX_OUTPUT_TOKENS,
    }
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.

@ndayiemile ndayiemile merged commit ca99205 into main Sep 22, 2025
1 check passed
@coveralls
Copy link

Pull Request Test Coverage Report for Build 17922042100

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+13.0%) to 92.641%

Totals Coverage Status
Change from base Build 17884742196: 13.0%
Covered Lines: 214
Relevant Lines: 231

💛 - Coveralls

@liamjdavis liamjdavis deleted the gemini branch September 22, 2025 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants