Spaces:
Runtime error
Runtime error
Sunanda commited on
Commit Β·
2a414bf
1
Parent(s): 15fa769
Initial sentiment app
Browse files- app.py +115 -0
- requirements.txt +4 -0
app.py
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
from huggingface_hub import InferenceClient
|
| 4 |
+
from docx import Document
|
| 5 |
+
|
| 6 |
+
# Hugging Face client
|
| 7 |
+
HF_TOKEN = os.getenv("HUGGINGFACE_API_KEY")
|
| 8 |
+
client = InferenceClient(api_key=HF_TOKEN)
|
| 9 |
+
promt = """
|
| 10 |
+
You are a senior software engineer reviewing .NET / C# code.
|
| 11 |
+
Give short, clear feedback in bullet points.
|
| 12 |
+
|
| 13 |
+
**Rules:**
|
| 14 |
+
Review the code and provide actionable points under these 4 areas:
|
| 15 |
+
1. **Code Standards** β Naming, formatting, magic numbers, comments
|
| 16 |
+
2. **Security** β SQL injection, input validation, hardcoded secrets, authentication issues
|
| 17 |
+
3. **Reusability** β Duplicate code, missing helper functions, not using libraries
|
| 18 |
+
4. **Refactoring** β Simplify complex code, performance improvements, better error handling
|
| 19 |
+
|
| 20 |
+
**Format:**
|
| 21 |
+
- Each suggestion must be a single concise line:
|
| 22 |
+
`Line X: Problem β Fix`
|
| 23 |
+
- Always **show both the incorrect and corrected examples** when suggesting naming or syntax improvements.
|
| 24 |
+
- Use **real corrected form** (e.g., `_AuthService` β `_authService`, not the same text again).
|
| 25 |
+
- Keep tone friendly, direct, and professional.
|
| 26 |
+
- Do not repeat identical feedback for multiple lines; combine where possible.
|
| 27 |
+
|
| 28 |
+
**Example Output:**
|
| 29 |
+
Line 12: Variable `_AuthService` should follow camelCase for private fields β rename to `_authService` same for others.
|
| 30 |
+
Line 35: Missing input validation for `username` β add sanitization before using it in queries.
|
| 31 |
+
Line 72: Duplicate code in `Login` and `Register` β extract shared logic into a helper method.
|
| 32 |
+
Line 90: Complex nested if-else β simplify with early returns.
|
| 33 |
+
"""
|
| 34 |
+
# Allowed file extensions
|
| 35 |
+
ALLOWED_EXTS = [".py", ".js", ".java", ".cs", ".cpp", ".ts"]
|
| 36 |
+
|
| 37 |
+
def analyze_code_with_ai(code_text: str, filename: str) -> str:
|
| 38 |
+
"""Send code to Hugging Face model for review."""
|
| 39 |
+
try:
|
| 40 |
+
completion = client.chat.completions.create(
|
| 41 |
+
model="meta-llama/Llama-3.1-8B-Instruct",
|
| 42 |
+
messages=[
|
| 43 |
+
{"role": "system", "content": f"{promt}"},
|
| 44 |
+
{"role": "user", "content": f"Review the following code from {filename}:\n\n{code_text}"}
|
| 45 |
+
]
|
| 46 |
+
)
|
| 47 |
+
return completion.choices[0].message["content"]
|
| 48 |
+
except Exception as e:
|
| 49 |
+
return f"β οΈ Error: {str(e)}"
|
| 50 |
+
|
| 51 |
+
def process_folder(folder_path):
|
| 52 |
+
"""Process all allowed code files in folder + subfolders."""
|
| 53 |
+
reviews = {}
|
| 54 |
+
for root, _, files in os.walk(folder_path):
|
| 55 |
+
for file in files:
|
| 56 |
+
if any(file.endswith(ext) for ext in ALLOWED_EXTS):
|
| 57 |
+
filepath = os.path.join(root, file)
|
| 58 |
+
with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
|
| 59 |
+
code = f.read()
|
| 60 |
+
reviews[file] = analyze_code_with_ai(code, file)
|
| 61 |
+
return reviews
|
| 62 |
+
|
| 63 |
+
def process_file(file_path):
|
| 64 |
+
"""Process a single uploaded file."""
|
| 65 |
+
filename = os.path.basename(file_path)
|
| 66 |
+
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
|
| 67 |
+
code = f.read()
|
| 68 |
+
return {filename: analyze_code_with_ai(code, filename)}
|
| 69 |
+
|
| 70 |
+
def generate_report(reviews, output_path="review_report.docx"):
|
| 71 |
+
"""Generate DOCX report."""
|
| 72 |
+
doc = Document()
|
| 73 |
+
doc.add_heading("Code Review Report", 0)
|
| 74 |
+
for fname, review in reviews.items():
|
| 75 |
+
doc.add_heading(fname, level=1)
|
| 76 |
+
doc.add_paragraph(review)
|
| 77 |
+
doc.save(output_path)
|
| 78 |
+
return output_path
|
| 79 |
+
|
| 80 |
+
def review_folder(folder_path):
|
| 81 |
+
reviews = process_folder(folder_path)
|
| 82 |
+
if not reviews:
|
| 83 |
+
return "β οΈ No code files found in folder.", None
|
| 84 |
+
report_path = generate_report(reviews)
|
| 85 |
+
return "\n\n".join([f"π {f}:\n{r}" for f, r in reviews.items()]), report_path
|
| 86 |
+
|
| 87 |
+
def review_single_file(file_obj):
|
| 88 |
+
reviews = process_file(file_obj.name)
|
| 89 |
+
if not reviews:
|
| 90 |
+
return "β οΈ Could not analyze file.", None
|
| 91 |
+
report_path = generate_report(reviews)
|
| 92 |
+
return "\n\n".join([f"π {f}:\n{r}" for f, r in reviews.items()]), report_path
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
# Gradio UI
|
| 96 |
+
with gr.Blocks() as demo:
|
| 97 |
+
gr.Markdown("# π€ AI Code Reviewer\nUpload a folder or single file to get review points + download DOCX report.")
|
| 98 |
+
|
| 99 |
+
with gr.Tab("π Review Folder"):
|
| 100 |
+
folder_input = gr.Textbox(label="Folder Path", placeholder="/path/to/project")
|
| 101 |
+
folder_btn = gr.Button("Run Review")
|
| 102 |
+
folder_output = gr.Textbox(label="AI Review Output", lines=15)
|
| 103 |
+
folder_file = gr.File(label="Download DOCX Report", type="filepath")
|
| 104 |
+
#folder_file = gr.DownloadButton(label="Download DOCX Report")
|
| 105 |
+
folder_btn.click(fn=review_folder, inputs=folder_input, outputs=[folder_output, folder_file])
|
| 106 |
+
|
| 107 |
+
with gr.Tab("π Review Single File"):
|
| 108 |
+
file_input = gr.File(label="Upload File", file_types=[".py", ".js", ".java", ".cs", ".cpp", ".ts"])
|
| 109 |
+
file_btn = gr.Button("Run Review")
|
| 110 |
+
file_output = gr.Textbox(label="AI Review Output", lines=15)
|
| 111 |
+
file_file = gr.File(label="Download DOCX Report", type="filepath")
|
| 112 |
+
#file_file = gr.DownloadButton(label="Download DOCX Report")
|
| 113 |
+
file_btn.click(fn=review_single_file, inputs=file_input, outputs=[file_output, file_file])
|
| 114 |
+
|
| 115 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
requests
|
| 2 |
+
python-docx
|
| 3 |
+
gradio
|
| 4 |
+
huggingface_hub
|