Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 51 additions & 12 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,38 @@
from embedding_description import main as classify_description
from embedding_url import main as classify_url
from aurora_api import main as aurora_classify
import re
import logging
from dotenv import load_dotenv

load_dotenv()

app = Flask(__name__)
CORS(app)

# Configure logging
log_level_str = os.environ.get("LOG_LEVEL", "INFO").upper()
log_level = getattr(logging, log_level_str, logging.INFO)
logging.basicConfig(
level=log_level,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)

@app.before_request
def log_request_info():
app.logger.info(f"Incoming Request: {request.method} {request.url} - Size: {request.content_length} bytes")

@app.after_request
def log_response_info(response):
app.logger.info(f"Outgoing Response: {request.method} {request.url} - Status: {response.status} - Size: {response.content_length} bytes")
return response

def is_valid_github_url(url):
if not url:
return False
pattern = r'^https?:\/\/(www\.)?github\.com\/[\w.-]+\/[\w.-]+\/?$'
return re.match(pattern, url) is not None



@app.route('/api/hello', methods=['GET'])
Expand All @@ -30,21 +57,24 @@ def classify_aurora():

if not projectDescription:
return jsonify({'error': 'Project description is required'}), 400

if not is_valid_github_url(projectUrl):
return jsonify({'error': 'A valid GitHub repository URL is required'}), 400



# 1. Aurora API Model (text-based)
print("\n===== RUNNING AURORA API MODEL =====")
app.logger.info("===== RUNNING AURORA API MODEL =====")
try:
aurora_result = aurora_classify(
text=projectDescription,
project_name=projectName,
project_url=projectUrl
)

print("Aurora API model completed successfully")
app.logger.info("Aurora API model completed successfully")
except Exception as e:
print(f"Aurora API model failed: {str(e)}")
app.logger.error(f"Aurora API model failed: {str(e)}", exc_info=True)
return jsonify({
"error": str(e),
"message": "Aurora API classification failed"
Expand Down Expand Up @@ -78,20 +108,23 @@ def classify_st_description():

if not projectDescription:
return jsonify({'error': 'Project description is required'}), 400

if not is_valid_github_url(projectUrl):
return jsonify({'error': 'A valid GitHub repository URL is required'}), 400


# 3. Sentence Transformer Description Model (text-based)
print("\n===== RUNNING SENTENCE TRANSFORMER DESCRIPTION MODEL =====")
app.logger.info("===== RUNNING SENTENCE TRANSFORMER DESCRIPTION MODEL =====")
try:
st_desc_result = classify_description(
project_description=projectDescription,
project_name=projectName,
project_url=projectUrl
)

print("ST Description model completed successfully")
app.logger.info("ST Description model completed successfully")
except Exception as e:
print(f"ST Description model failed: {str(e)}")
app.logger.error(f"ST Description model failed: {str(e)}", exc_info=True)
st_desc_result = {
"error": str(e),
"message": "Sentence Transformer Description model classification failed"
Expand Down Expand Up @@ -121,27 +154,30 @@ def classify_st_url():

if not projectDescription:
return jsonify({'error': 'Project description is required'}), 400

if not is_valid_github_url(projectUrl):
return jsonify({'error': 'A valid GitHub repository URL is required'}), 400



# 2. Sentence Transformer URL Model (GitHub URL-based)
print("\n===== RUNNING SENTENCE TRANSFORMER URL MODEL =====")
app.logger.info("===== RUNNING SENTENCE TRANSFORMER URL MODEL =====")
if projectUrl:
try:
st_url_result = classify_url(projectUrl)

print("ST URL model completed successfully")
app.logger.info("ST URL model completed successfully")
except ValueError as ve:
print(f"ST URL model invalid URL: {str(ve)}")
app.logger.warning(f"ST URL model invalid URL: {str(ve)}")
return jsonify({'error': str(ve)}), 400
except requests.exceptions.HTTPError as he:
print(f"ST URL model HTTP Error: {str(he)}")
app.logger.error(f"ST URL model HTTP Error: {str(he)}", exc_info=True)
return jsonify({
"error": f"Failed to fetch repository data. Please ensure the repository is public and exists. ({str(he)})",
"message": "Sentence Transformer URL model classification failed"
}), 400
except Exception as e:
print(f"ST URL model failed: {str(e)}")
app.logger.error(f"ST URL model failed: {str(e)}", exc_info=True)
return jsonify({
"error": str(e),
"message": "Sentence Transformer URL model classification failed"
Expand Down Expand Up @@ -171,6 +207,9 @@ def osdg_external_api():

if not projectDescription:
return jsonify({'error': 'Project description is required'}), 400

if not is_valid_github_url(projectUrl):
return jsonify({'error': 'A valid GitHub repository URL is required'}), 400

# Call the external OSDG API
try:
Expand All @@ -187,7 +226,7 @@ def osdg_external_api():
osdg_response.raise_for_status() # Raise an error for bad status codes
osdg_result = osdg_response.json()
except requests.exceptions.RequestException as e:
print(f"OSDG API request failed: {str(e)}")
app.logger.error(f"OSDG API request failed: {str(e)}", exc_info=True)
return jsonify({
"error": f"Failed to connect to OSDG API: {str(e)}",
"message": "OSDG API classification failed"
Expand Down
7 changes: 5 additions & 2 deletions backend/aurora_api.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import requests
import json
import logging
from sdg_constants import SDG_LABELS_DICT as SDG_LABELS

logger = logging.getLogger(__name__)


def main(text: str, project_name: str = None, project_url: str = None):
"""
Expand Down Expand Up @@ -74,9 +77,9 @@ def main(text: str, project_name: str = None, project_url: str = None):
if score > 0.5:
sdg_predictions[sdg_name] = float(f"{float(score):.3f}")
else:
print(f"DEBUG - Warning: Could not extract SDG name from prediction {idx}")
logger.warning(f"Could not extract SDG name from prediction {idx}")
else:
print(f"DEBUG - Warning: Prediction {idx} is not a dict: {type(pred)}")
logger.warning(f"Prediction {idx} is not a dict: {type(pred)}")

# Format output to match embedding_url.py structure
formatted_result = {
Expand Down
32 changes: 15 additions & 17 deletions frontend/components/mainScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,31 @@ const MainScreen: React.FC<{
const handleFormSubmit = async (e: React.FormEvent) => {
e.preventDefault();

if (
!projectName ||
!projectUrl ||
!projectDescription
// !problemStatement ||
// !longTermGoal ||
// !solutionApproach ||
// !targetAudience
) {
const trimmedName = projectName.trim();
const trimmedUrl = projectUrl.trim();
const trimmedDesc = projectDescription.trim();

if (!trimmedName || !trimmedUrl || !trimmedDesc) {
setUploadMsg("Please fill in all required fields before submitting.");
return;
}

if (projectUrl.includes("github.com") === false) {
setUploadMsg("Please enter a valid GitHub repository URL.");
// GitHub URL validation regex
const githubUrlRegex = /^https?:\/\/(www\.)?github\.com\/[\w.-]+\/[\w.-]+\/?$/;
if (!githubUrlRegex.test(trimmedUrl)) {
setUploadMsg("Please enter a valid GitHub repository URL (e.g., https://github.com/username/repository).");
return;
}

const finalizedData = {
projectName: projectName,
projectUrl: projectUrl,
projectDescription: projectDescription,
projectName: trimmedName,
projectUrl: trimmedUrl,
projectDescription: trimmedDesc,
};

localStorage.setItem("projectDescription", projectDescription);
localStorage.setItem("projectName", projectName);
localStorage.setItem("projectUrl", projectUrl);
localStorage.setItem("projectDescription", trimmedDesc);
localStorage.setItem("projectName", trimmedName);
localStorage.setItem("projectUrl", trimmedUrl);

try {
setIsUploading(true);
Expand Down
11 changes: 11 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.