Spaces:
Sleeping
Sleeping
arun3676 commited on
Commit ·
5c6379b
1
Parent(s): ddf8352
Initial commit: AI Code Analyzer with fine-tuned model support
Browse files- Multi-model code analysis with OpenAI, Anthropic, DeepSeek APIs
- Custom fine-tuned DeepSeek model for enhanced analysis
- Matrix-inspired Streamlit UI with professional styling
- Support for both local and remote model deployment
- Comprehensive documentation and integration guides
- Ready for Hugging Face deployment
- .gitignore +24 -1
- API_SETUP.md +0 -44
- INTEGRATION_GUIDE.md +368 -0
- INTEGRATION_SUMMARY.md +253 -0
- MCP_SETUP_GUIDE.md +142 -0
- MODEL_UPGRADE_GUIDE.md +155 -0
- NEXT_STEPS_CHECKLIST.md +263 -0
- Procfile +0 -1
- README.md +134 -108
- additional_samples.py +73 -0
- analyst_dataset.jsonl +34 -0
- analyst_dataset_expanded.jsonl +0 -0
- app.py +0 -340
- detailed_model_comparison.py +324 -0
- finetune.py +274 -0
- finetune_improved.py +277 -0
- inference_demo.py +57 -0
- launch.py +0 -111
- launch_matrix.py +0 -144
- matrix_analyzer_optimized.py +262 -0
- matrix_app.py +0 -638
- matrix_final.py +67 -11
- matrix_final_backup.py +0 -978
- model_comparison.py +175 -0
- netlify.toml +0 -9
- optimized_code_analyzer.py +466 -0
- optimized_code_analyzer_enhanced.py +542 -0
- requirements.txt +10 -1
- streamlit.bat +0 -2
- test_app.py +0 -34
.gitignore
CHANGED
|
@@ -41,4 +41,27 @@ test_results.txt
|
|
| 41 |
|
| 42 |
# Deployment
|
| 43 |
render.yaml.bak
|
| 44 |
-
netlify.toml.bak
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
# Deployment
|
| 43 |
render.yaml.bak
|
| 44 |
+
netlify.toml.bak
|
| 45 |
+
|
| 46 |
+
# Model files (too large for GitHub)
|
| 47 |
+
fine-tuned-analyst/
|
| 48 |
+
*.bin
|
| 49 |
+
*.safetensors
|
| 50 |
+
checkpoint-*/
|
| 51 |
+
lora_adapters/
|
| 52 |
+
runs/
|
| 53 |
+
|
| 54 |
+
# Training data
|
| 55 |
+
additional_samples.json
|
| 56 |
+
mlruns/
|
| 57 |
+
|
| 58 |
+
# Temporary files
|
| 59 |
+
complete_notebook.py
|
| 60 |
+
create_colab_notebook.py
|
| 61 |
+
create_dataset.py
|
| 62 |
+
generate_full_dataset.py
|
| 63 |
+
test_finetuned_local.py
|
| 64 |
+
|
| 65 |
+
# Cache directories
|
| 66 |
+
cache/
|
| 67 |
+
.cache/
|
API_SETUP.md
DELETED
|
@@ -1,44 +0,0 @@
|
|
| 1 |
-
# API Setup Guide
|
| 2 |
-
|
| 3 |
-
## Setting up DeepSeek API Key
|
| 4 |
-
|
| 5 |
-
1. **Get your DeepSeek API Key**:
|
| 6 |
-
- Go to [DeepSeek Console](https://platform.deepseek.com/)
|
| 7 |
-
- Sign up or log in
|
| 8 |
-
- Navigate to API Keys section
|
| 9 |
-
- Create a new API key
|
| 10 |
-
|
| 11 |
-
2. **Add the key to your environment**:
|
| 12 |
-
- Create a `.env` file in your project root
|
| 13 |
-
- Add: `DEEPSEEK_API_KEY=your_actual_api_key_here`
|
| 14 |
-
- **Important**: Use your real API key, not placeholder text like `****`
|
| 15 |
-
|
| 16 |
-
3. **Other supported APIs**:
|
| 17 |
-
```
|
| 18 |
-
OPENAI_API_KEY=your_openai_key_here
|
| 19 |
-
ANTHROPIC_API_KEY=your_claude_key_here
|
| 20 |
-
GEMINI_API_KEY=your_gemini_key_here
|
| 21 |
-
```
|
| 22 |
-
|
| 23 |
-
## Common Issues & Solutions
|
| 24 |
-
|
| 25 |
-
### DeepSeek Authentication Error (401)
|
| 26 |
-
- **Problem**: Error message "Authentication Fails, Your api key: ****here is invalid"
|
| 27 |
-
- **Solution**:
|
| 28 |
-
1. Double-check your API key is correct
|
| 29 |
-
2. Make sure there are no extra spaces or quotes
|
| 30 |
-
3. Verify the key is active in DeepSeek console
|
| 31 |
-
4. Try regenerating the API key
|
| 32 |
-
|
| 33 |
-
### Button Not Clickable
|
| 34 |
-
- **Fixed**: The "Analyze Code" button is now always clickable
|
| 35 |
-
- **Usage**: Just paste your code and click "Analyze Code"
|
| 36 |
-
- No need to wait for any delays
|
| 37 |
-
|
| 38 |
-
## Running the Application
|
| 39 |
-
|
| 40 |
-
```bash
|
| 41 |
-
python -m streamlit run matrix_final.py --server.port 8500
|
| 42 |
-
```
|
| 43 |
-
|
| 44 |
-
Access at: http://localhost:8500
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
INTEGRATION_GUIDE.md
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Integration Guide: Fine-tuned Model with Your Code Analyzer
|
| 2 |
+
|
| 3 |
+
This guide explains how to integrate your fine-tuned DeepSeek model with the existing code analyzer app.
|
| 4 |
+
|
| 5 |
+
## 📋 What You Have Now
|
| 6 |
+
|
| 7 |
+
After completing the Colab training, you have:
|
| 8 |
+
- ✅ Fine-tuned DeepSeek model adapters (~20MB)
|
| 9 |
+
- ✅ Enhanced analyzer class supporting both models
|
| 10 |
+
- ✅ Original CodeT5+ model still working
|
| 11 |
+
- ✅ All existing UI features preserved
|
| 12 |
+
|
| 13 |
+
## 🔄 Integration Steps
|
| 14 |
+
|
| 15 |
+
### Step 1: Download Your Fine-tuned Model from Colab
|
| 16 |
+
|
| 17 |
+
In your final Colab cell, you saved the model to Google Drive. Now download it:
|
| 18 |
+
|
| 19 |
+
**Option A: From Google Drive**
|
| 20 |
+
1. Go to Google Drive → `MyDrive/ai-code-analyzer/`
|
| 21 |
+
2. Download the `fine-tuned-analyst` folder
|
| 22 |
+
3. Place it in your project root: `C:\Users\arunk\professional\ai-code-analyzer\fine-tuned-analyst\`
|
| 23 |
+
|
| 24 |
+
**Option B: Download Directly from Colab**
|
| 25 |
+
```python
|
| 26 |
+
# Run this in Colab to create a downloadable ZIP
|
| 27 |
+
import shutil
|
| 28 |
+
shutil.make_archive('fine-tuned-analyst', 'zip', './fine-tuned-analyst')
|
| 29 |
+
|
| 30 |
+
from google.colab import files
|
| 31 |
+
files.download('fine-tuned-analyst.zip')
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
Then extract the ZIP in your project root.
|
| 35 |
+
|
| 36 |
+
### Step 2: Install Required Dependencies
|
| 37 |
+
|
| 38 |
+
Update your `requirements.txt` to include PEFT:
|
| 39 |
+
|
| 40 |
+
```bash
|
| 41 |
+
# Add this line to requirements.txt
|
| 42 |
+
peft>=0.7.0
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
Install it:
|
| 46 |
+
```bash
|
| 47 |
+
pip install peft
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
### Step 3: Test the Enhanced Analyzer Locally
|
| 51 |
+
|
| 52 |
+
Run the test script to verify everything works:
|
| 53 |
+
|
| 54 |
+
```bash
|
| 55 |
+
python optimized_code_analyzer_enhanced.py
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
You should see:
|
| 59 |
+
- ✅ CodeT5+ analysis
|
| 60 |
+
- ✅ Fine-tuned DeepSeek analysis
|
| 61 |
+
- ✅ Model comparison
|
| 62 |
+
|
| 63 |
+
### Step 4: Update Your Streamlit UI
|
| 64 |
+
|
| 65 |
+
Replace the analyzer import in `matrix_final.py`:
|
| 66 |
+
|
| 67 |
+
**Find this (around line 8):**
|
| 68 |
+
```python
|
| 69 |
+
from optimized_code_analyzer import OptimizedCodeAnalyzer
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
**Replace with:**
|
| 73 |
+
```python
|
| 74 |
+
from optimized_code_analyzer_enhanced import EnhancedCodeAnalyzer
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
**Find this (around line 287):**
|
| 78 |
+
```python
|
| 79 |
+
@st.cache_resource
|
| 80 |
+
def get_local_analyzer():
|
| 81 |
+
return OptimizedCodeAnalyzer(
|
| 82 |
+
model_id="Salesforce/codet5p-220m",
|
| 83 |
+
precision="fp16",
|
| 84 |
+
quick_max_new_tokens=180,
|
| 85 |
+
detailed_max_new_tokens=240,
|
| 86 |
+
)
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
**Replace with:**
|
| 90 |
+
```python
|
| 91 |
+
@st.cache_resource
|
| 92 |
+
def get_local_analyzer(model_type="codet5"):
|
| 93 |
+
return EnhancedCodeAnalyzer(
|
| 94 |
+
model_type=model_type,
|
| 95 |
+
precision="fp16",
|
| 96 |
+
quick_max_new_tokens=180,
|
| 97 |
+
detailed_max_new_tokens=300,
|
| 98 |
+
)
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
### Step 5: Add Model Selector to Sidebar
|
| 102 |
+
|
| 103 |
+
Add this to your sidebar (around line 490, in the sidebar section):
|
| 104 |
+
|
| 105 |
+
```python
|
| 106 |
+
# Model Selection
|
| 107 |
+
st.sidebar.markdown("---")
|
| 108 |
+
st.sidebar.markdown("### 🤖 AI Model Selection")
|
| 109 |
+
model_choice = st.sidebar.radio(
|
| 110 |
+
"Choose Analysis Model:",
|
| 111 |
+
["CodeT5+ (Fast)", "Fine-tuned DeepSeek (Accurate)"],
|
| 112 |
+
help="CodeT5+ is faster, Fine-tuned model gives more detailed analysis"
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
model_type = "codet5" if "CodeT5+" in model_choice else "deepseek-finetuned"
|
| 116 |
+
```
|
| 117 |
+
|
| 118 |
+
### Step 6: Update the Analysis Call
|
| 119 |
+
|
| 120 |
+
Find where the analyzer is called (around line 600+) and update it:
|
| 121 |
+
|
| 122 |
+
**Find something like:**
|
| 123 |
+
```python
|
| 124 |
+
local_analyzer = get_local_analyzer()
|
| 125 |
+
result = local_analyzer.analyze_code_fast(code)
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
**Replace with:**
|
| 129 |
+
```python
|
| 130 |
+
local_analyzer = get_local_analyzer(model_type)
|
| 131 |
+
result = local_analyzer.analyze_code_fast(code)
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
### Step 7: Test Everything
|
| 135 |
+
|
| 136 |
+
Run your Streamlit app:
|
| 137 |
+
```bash
|
| 138 |
+
streamlit run matrix_final.py
|
| 139 |
+
```
|
| 140 |
+
|
| 141 |
+
Test both models:
|
| 142 |
+
1. Select "CodeT5+ (Fast)" → Run analysis → Should work as before
|
| 143 |
+
2. Select "Fine-tuned DeepSeek (Accurate)" → Run analysis → Should give detailed analysis with quality scores
|
| 144 |
+
|
| 145 |
+
## 📊 What Each Model Does
|
| 146 |
+
|
| 147 |
+
### CodeT5+ (Base Model)
|
| 148 |
+
- **Speed**: ⚡ Fast (2-3 seconds)
|
| 149 |
+
- **Memory**: ~1GB
|
| 150 |
+
- **Analysis**: General code analysis
|
| 151 |
+
- **Best for**: Quick checks, batch processing
|
| 152 |
+
- **Quality**: Good for basic issues
|
| 153 |
+
|
| 154 |
+
### Fine-tuned DeepSeek (Your Model)
|
| 155 |
+
- **Speed**: 🚀 Moderate (3-5 seconds)
|
| 156 |
+
- **Memory**: ~1.5GB
|
| 157 |
+
- **Analysis**: Detailed with quality scores (1-100)
|
| 158 |
+
- **Best for**: Deep analysis, learning, production code
|
| 159 |
+
- **Quality**: Excellent - trained on your specific patterns
|
| 160 |
+
- **Output format**:
|
| 161 |
+
- Quality Score (1-100)
|
| 162 |
+
- Bugs section
|
| 163 |
+
- Performance issues
|
| 164 |
+
- Security concerns
|
| 165 |
+
- Improvement suggestions with code examples
|
| 166 |
+
|
| 167 |
+
## 🎯 Key Features of the Enhanced System
|
| 168 |
+
|
| 169 |
+
### 1. Dual Model Support
|
| 170 |
+
- Seamlessly switch between models
|
| 171 |
+
- Separate caching for each model
|
| 172 |
+
- No breaking changes to existing code
|
| 173 |
+
|
| 174 |
+
### 2. Improved Analysis Quality
|
| 175 |
+
Your fine-tuned model provides:
|
| 176 |
+
- **Structured output**: Quality score, bugs, performance, security
|
| 177 |
+
- **Code examples**: Shows how to fix issues
|
| 178 |
+
- **Contextual understanding**: Trained on your dataset patterns
|
| 179 |
+
- **Consistent formatting**: Always includes all sections
|
| 180 |
+
|
| 181 |
+
### 3. Memory Efficient
|
| 182 |
+
- LoRA adapters are tiny (~20MB vs 1GB+ full model)
|
| 183 |
+
- Base model shared, adapters loaded on demand
|
| 184 |
+
- Can deploy both models without doubling memory
|
| 185 |
+
|
| 186 |
+
## 🚀 Deployment Options
|
| 187 |
+
|
| 188 |
+
### Option 1: Local Deployment (Current)
|
| 189 |
+
**Pros:**
|
| 190 |
+
- Free
|
| 191 |
+
- Fast
|
| 192 |
+
- Full control
|
| 193 |
+
- Easy testing
|
| 194 |
+
|
| 195 |
+
**Cons:**
|
| 196 |
+
- Only you can use it
|
| 197 |
+
- Needs your computer running
|
| 198 |
+
|
| 199 |
+
**Setup:** Already working! Just use Streamlit locally.
|
| 200 |
+
|
| 201 |
+
### Option 2: Hugging Face Spaces (Recommended)
|
| 202 |
+
**Pros:**
|
| 203 |
+
- FREE hosting
|
| 204 |
+
- Automatic HTTPS
|
| 205 |
+
- Share with anyone
|
| 206 |
+
- GPU available (paid tier)
|
| 207 |
+
|
| 208 |
+
**Setup:**
|
| 209 |
+
1. Create account on huggingface.co
|
| 210 |
+
2. Create new Space (Streamlit)
|
| 211 |
+
3. Upload files:
|
| 212 |
+
- `matrix_final.py`
|
| 213 |
+
- `optimized_code_analyzer_enhanced.py`
|
| 214 |
+
- `requirements.txt`
|
| 215 |
+
- `fine-tuned-analyst/` folder
|
| 216 |
+
4. Add `app.py`:
|
| 217 |
+
```python
|
| 218 |
+
# app.py (for HF Spaces)
|
| 219 |
+
import subprocess
|
| 220 |
+
subprocess.run(["streamlit", "run", "matrix_final.py"])
|
| 221 |
+
```
|
| 222 |
+
|
| 223 |
+
### Option 3: Railway.app
|
| 224 |
+
**Cost:** $5/month
|
| 225 |
+
**Memory:** Up to 8GB
|
| 226 |
+
**Speed:** Faster than HF Spaces
|
| 227 |
+
|
| 228 |
+
**Setup:**
|
| 229 |
+
1. Connect GitHub repo
|
| 230 |
+
2. Set start command: `streamlit run matrix_final.py --server.port $PORT`
|
| 231 |
+
3. Deploy
|
| 232 |
+
|
| 233 |
+
### Option 4: Render.com
|
| 234 |
+
**Cost:** FREE tier available
|
| 235 |
+
**Memory:** 512MB (might be tight)
|
| 236 |
+
**Speed:** Good
|
| 237 |
+
|
| 238 |
+
**Setup:**
|
| 239 |
+
1. Connect repo
|
| 240 |
+
2. Use Docker:
|
| 241 |
+
```dockerfile
|
| 242 |
+
FROM python:3.11-slim
|
| 243 |
+
WORKDIR /app
|
| 244 |
+
COPY requirements.txt .
|
| 245 |
+
RUN pip install -r requirements.txt
|
| 246 |
+
COPY . .
|
| 247 |
+
CMD streamlit run matrix_final.py --server.port $PORT
|
| 248 |
+
```
|
| 249 |
+
|
| 250 |
+
## 🐛 Troubleshooting
|
| 251 |
+
|
| 252 |
+
### Issue: "fine-tuned-analyst folder not found"
|
| 253 |
+
**Solution:** Make sure the folder is in your project root with these files:
|
| 254 |
+
```
|
| 255 |
+
fine-tuned-analyst/
|
| 256 |
+
├── adapter_config.json
|
| 257 |
+
├── adapter_model.bin (or adapter_model.safetensors)
|
| 258 |
+
├── tokenizer_config.json
|
| 259 |
+
└── special_tokens_map.json
|
| 260 |
+
```
|
| 261 |
+
|
| 262 |
+
### Issue: "PEFT not installed"
|
| 263 |
+
**Solution:**
|
| 264 |
+
```bash
|
| 265 |
+
pip install peft
|
| 266 |
+
```
|
| 267 |
+
|
| 268 |
+
### Issue: "Model too slow"
|
| 269 |
+
**Solution:**
|
| 270 |
+
- Use "quick" mode instead of "detailed"
|
| 271 |
+
- Reduce `max_new_tokens` to 150
|
| 272 |
+
- Use INT8 or INT4 quantization
|
| 273 |
+
|
| 274 |
+
### Issue: "Out of memory"
|
| 275 |
+
**Solution:**
|
| 276 |
+
- Close other applications
|
| 277 |
+
- Use CodeT5+ instead (smaller)
|
| 278 |
+
- Enable quantization: `precision="int8"`
|
| 279 |
+
|
| 280 |
+
## 📚 Understanding the Libraries Used
|
| 281 |
+
|
| 282 |
+
### Core Libraries
|
| 283 |
+
|
| 284 |
+
**Transformers** (`transformers`)
|
| 285 |
+
- What: Hugging Face's library for AI models
|
| 286 |
+
- Does: Loads models, tokenizers, handles generation
|
| 287 |
+
- Used for: Loading DeepSeek and CodeT5+ models
|
| 288 |
+
|
| 289 |
+
**PEFT** (`peft`)
|
| 290 |
+
- What: Parameter Efficient Fine-Tuning
|
| 291 |
+
- Does: Loads LoRA adapters efficiently
|
| 292 |
+
- Used for: Your fine-tuned model adapters
|
| 293 |
+
|
| 294 |
+
**PyTorch** (`torch`)
|
| 295 |
+
- What: Deep learning framework
|
| 296 |
+
- Does: Runs neural networks on GPU/CPU
|
| 297 |
+
- Used for: Model inference, tensor operations
|
| 298 |
+
|
| 299 |
+
**Streamlit** (`streamlit`)
|
| 300 |
+
- What: Web app framework for Python
|
| 301 |
+
- Does: Creates interactive UI
|
| 302 |
+
- Used for: Your code analyzer interface
|
| 303 |
+
|
| 304 |
+
### How They Work Together
|
| 305 |
+
|
| 306 |
+
```
|
| 307 |
+
User Input (Streamlit)
|
| 308 |
+
↓
|
| 309 |
+
EnhancedCodeAnalyzer
|
| 310 |
+
↓
|
| 311 |
+
Transformers (loads base model)
|
| 312 |
+
↓
|
| 313 |
+
PEFT (loads adapters)
|
| 314 |
+
↓
|
| 315 |
+
PyTorch (runs inference)
|
| 316 |
+
↓
|
| 317 |
+
Result → Streamlit UI
|
| 318 |
+
```
|
| 319 |
+
|
| 320 |
+
## 🎓 Next Steps
|
| 321 |
+
|
| 322 |
+
1. **Test both models** with various code samples
|
| 323 |
+
2. **Compare quality** - which model works better for your use cases?
|
| 324 |
+
3. **Expand dataset** - Add more samples and retrain (only takes 20 minutes!)
|
| 325 |
+
4. **Deploy** - Choose a hosting option and share with others
|
| 326 |
+
5. **Iterate** - Collect feedback and improve
|
| 327 |
+
|
| 328 |
+
## 💡 Tips for Best Results
|
| 329 |
+
|
| 330 |
+
### When to Use CodeT5+
|
| 331 |
+
- Quick syntax checks
|
| 332 |
+
- Batch processing many files
|
| 333 |
+
- Resource-constrained environments
|
| 334 |
+
- Simple code reviews
|
| 335 |
+
|
| 336 |
+
### When to Use Fine-tuned DeepSeek
|
| 337 |
+
- Production code reviews
|
| 338 |
+
- Learning/education
|
| 339 |
+
- Complex analysis needed
|
| 340 |
+
- When quality > speed
|
| 341 |
+
- Security audits
|
| 342 |
+
|
| 343 |
+
## 🎉 Congratulations!
|
| 344 |
+
|
| 345 |
+
You've successfully:
|
| 346 |
+
- ✅ Fine-tuned a language model
|
| 347 |
+
- ✅ Integrated it with your app
|
| 348 |
+
- ✅ Created a dual-model system
|
| 349 |
+
- ✅ Learned about model deployment
|
| 350 |
+
- ✅ Built a production-ready tool
|
| 351 |
+
|
| 352 |
+
Your code analyzer now has:
|
| 353 |
+
- **2 AI models** to choose from
|
| 354 |
+
- **Professional quality** analysis
|
| 355 |
+
- **Scalable architecture** for future improvements
|
| 356 |
+
- **Production-ready** code
|
| 357 |
+
|
| 358 |
+
## 📞 Support
|
| 359 |
+
|
| 360 |
+
If you need help:
|
| 361 |
+
1. Check error messages carefully
|
| 362 |
+
2. Review this guide
|
| 363 |
+
3. Test with simple code first
|
| 364 |
+
4. Compare with working examples
|
| 365 |
+
5. Ask for help with specific errors
|
| 366 |
+
|
| 367 |
+
Happy coding! 🚀
|
| 368 |
+
|
INTEGRATION_SUMMARY.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Integration Complete! 🎉
|
| 2 |
+
|
| 3 |
+
## What We've Built
|
| 4 |
+
|
| 5 |
+
You now have a **dual-model code analyzer** that supports both:
|
| 6 |
+
1. **CodeT5+ (Base)** - Fast, lightweight analysis
|
| 7 |
+
2. **Fine-tuned DeepSeek** - Detailed, accurate analysis with quality scores
|
| 8 |
+
|
| 9 |
+
## Files Created
|
| 10 |
+
|
| 11 |
+
### ✅ Core Files
|
| 12 |
+
1. **`optimized_code_analyzer_enhanced.py`** - New analyzer supporting both models
|
| 13 |
+
2. **`INTEGRATION_GUIDE.md`** - Complete step-by-step integration instructions
|
| 14 |
+
3. **`test_finetuned_local.py`** - Test script to verify everything works
|
| 15 |
+
4. **`INTEGRATION_SUMMARY.md`** - This file (quick reference)
|
| 16 |
+
|
| 17 |
+
### 📦 What You Need from Colab
|
| 18 |
+
- `fine-tuned-analyst/` folder from Google Drive containing your trained model adapters
|
| 19 |
+
|
| 20 |
+
## Quick Start (3 Steps)
|
| 21 |
+
|
| 22 |
+
### Step 1: Get Your Model
|
| 23 |
+
Download the `fine-tuned-analyst` folder from Google Drive (saved in Cell 9 of Colab) and place it in your project root:
|
| 24 |
+
```
|
| 25 |
+
C:\Users\arunk\professional\ai-code-analyzer\fine-tuned-analyst\
|
| 26 |
+
```
|
| 27 |
+
|
| 28 |
+
### Step 2: Install Dependencies
|
| 29 |
+
```bash
|
| 30 |
+
pip install peft
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
### Step 3: Test It
|
| 34 |
+
```bash
|
| 35 |
+
python test_finetuned_local.py
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
If all checks pass ✅, you're ready to integrate with your UI!
|
| 39 |
+
|
| 40 |
+
## Integration with Streamlit UI
|
| 41 |
+
|
| 42 |
+
### Quick Changes to `matrix_final.py`
|
| 43 |
+
|
| 44 |
+
**Change 1: Update Import (Line ~8)**
|
| 45 |
+
```python
|
| 46 |
+
# OLD:
|
| 47 |
+
from optimized_code_analyzer import OptimizedCodeAnalyzer
|
| 48 |
+
|
| 49 |
+
# NEW:
|
| 50 |
+
from optimized_code_analyzer_enhanced import EnhancedCodeAnalyzer
|
| 51 |
+
```
|
| 52 |
+
|
| 53 |
+
**Change 2: Update Analyzer Function (Line ~287)**
|
| 54 |
+
```python
|
| 55 |
+
# OLD:
|
| 56 |
+
@st.cache_resource
|
| 57 |
+
def get_local_analyzer():
|
| 58 |
+
return OptimizedCodeAnalyzer(
|
| 59 |
+
model_id="Salesforce/codet5p-220m",
|
| 60 |
+
precision="fp16",
|
| 61 |
+
quick_max_new_tokens=180,
|
| 62 |
+
detailed_max_new_tokens=240,
|
| 63 |
+
)
|
| 64 |
+
|
| 65 |
+
# NEW:
|
| 66 |
+
@st.cache_resource
|
| 67 |
+
def get_local_analyzer(model_type="codet5"):
|
| 68 |
+
return EnhancedCodeAnalyzer(
|
| 69 |
+
model_type=model_type,
|
| 70 |
+
precision="fp16",
|
| 71 |
+
quick_max_new_tokens=180,
|
| 72 |
+
detailed_max_new_tokens=300,
|
| 73 |
+
)
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
**Change 3: Add Model Selector to Sidebar (Add after line ~490)**
|
| 77 |
+
```python
|
| 78 |
+
# Model Selection
|
| 79 |
+
st.sidebar.markdown("---")
|
| 80 |
+
st.sidebar.markdown("### 🤖 AI Model Selection")
|
| 81 |
+
model_choice = st.sidebar.radio(
|
| 82 |
+
"Choose Analysis Model:",
|
| 83 |
+
["CodeT5+ (Fast)", "Fine-tuned DeepSeek (Accurate)"],
|
| 84 |
+
help="CodeT5+ is faster, Fine-tuned model gives more detailed analysis"
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
model_type = "codet5" if "CodeT5+" in model_choice else "deepseek-finetuned"
|
| 88 |
+
```
|
| 89 |
+
|
| 90 |
+
**Change 4: Update Analysis Calls**
|
| 91 |
+
Find places where analyzer is called and add `model_type` parameter:
|
| 92 |
+
```python
|
| 93 |
+
# OLD:
|
| 94 |
+
local_analyzer = get_local_analyzer()
|
| 95 |
+
|
| 96 |
+
# NEW:
|
| 97 |
+
local_analyzer = get_local_analyzer(model_type)
|
| 98 |
+
```
|
| 99 |
+
|
| 100 |
+
## What Each Model Does
|
| 101 |
+
|
| 102 |
+
### CodeT5+ (Fast) ⚡
|
| 103 |
+
- **Speed**: 2-3 seconds
|
| 104 |
+
- **Memory**: ~1GB
|
| 105 |
+
- **Output**: General analysis
|
| 106 |
+
- **Best for**: Quick checks
|
| 107 |
+
|
| 108 |
+
### Fine-tuned DeepSeek (Accurate) 🎯
|
| 109 |
+
- **Speed**: 3-5 seconds
|
| 110 |
+
- **Memory**: ~1.5GB
|
| 111 |
+
- **Output**:
|
| 112 |
+
- Quality Score: 35/100
|
| 113 |
+
- Bugs section with specifics
|
| 114 |
+
- Performance issues
|
| 115 |
+
- Security concerns
|
| 116 |
+
- Improvement suggestions with code examples
|
| 117 |
+
- **Best for**: Production code, learning, detailed reviews
|
| 118 |
+
|
| 119 |
+
## Example Output
|
| 120 |
+
|
| 121 |
+
Your fine-tuned model gives structured output like:
|
| 122 |
+
|
| 123 |
+
```
|
| 124 |
+
Quality Score: 35/100
|
| 125 |
+
|
| 126 |
+
BUGS:
|
| 127 |
+
- No error handling
|
| 128 |
+
- Infinite recursion possible
|
| 129 |
+
|
| 130 |
+
PERFORMANCE ISSUES:
|
| 131 |
+
- Recursive calls cause exponential time complexity
|
| 132 |
+
|
| 133 |
+
SECURITY CONCERNS:
|
| 134 |
+
- No input validation
|
| 135 |
+
|
| 136 |
+
IMPROVEMENTS:
|
| 137 |
+
1. Use memoization to avoid recursion
|
| 138 |
+
2. Add input validation
|
| 139 |
+
|
| 140 |
+
Example improved code:
|
| 141 |
+
[Shows working code with fixes]
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
## Testing Checklist
|
| 145 |
+
|
| 146 |
+
- [ ] Run `test_finetuned_local.py` - all checks pass
|
| 147 |
+
- [ ] Update `matrix_final.py` imports
|
| 148 |
+
- [ ] Add model selector to sidebar
|
| 149 |
+
- [ ] Test with Streamlit: `streamlit run matrix_final.py`
|
| 150 |
+
- [ ] Try both models with sample code
|
| 151 |
+
- [ ] Verify quality scores appear for fine-tuned model
|
| 152 |
+
- [ ] Check caching works for both models
|
| 153 |
+
|
| 154 |
+
## Troubleshooting
|
| 155 |
+
|
| 156 |
+
| Issue | Solution |
|
| 157 |
+
|-------|----------|
|
| 158 |
+
| "fine-tuned-analyst not found" | Download from Google Drive, place in project root |
|
| 159 |
+
| "PEFT not installed" | Run `pip install peft` |
|
| 160 |
+
| "Model too slow" | Use CodeT5+ or enable quantization |
|
| 161 |
+
| "Out of memory" | Close other apps or use CodeT5+ |
|
| 162 |
+
|
| 163 |
+
## What You Learned
|
| 164 |
+
|
| 165 |
+
✅ **Fine-tuning LLMs** with LoRA/QLoRA
|
| 166 |
+
✅ **Google Colab** for GPU training
|
| 167 |
+
✅ **Model integration** with existing apps
|
| 168 |
+
✅ **Dual-model architecture** for flexibility
|
| 169 |
+
✅ **Production deployment** considerations
|
| 170 |
+
|
| 171 |
+
## Next Steps (Choose One)
|
| 172 |
+
|
| 173 |
+
### Option A: Deploy Locally (Easiest)
|
| 174 |
+
Just run `streamlit run matrix_final.py` - you're done!
|
| 175 |
+
|
| 176 |
+
### Option B: Deploy to Cloud (Share with Others)
|
| 177 |
+
1. **Hugging Face Spaces** (FREE) - Follow INTEGRATION_GUIDE.md
|
| 178 |
+
2. **Railway.app** ($5/month) - Best performance
|
| 179 |
+
3. **Render.com** (FREE tier) - Good alternative
|
| 180 |
+
|
| 181 |
+
### Option C: Improve the Model
|
| 182 |
+
1. Add more training samples (up to 150-200)
|
| 183 |
+
2. Retrain in Colab (only takes 20 minutes!)
|
| 184 |
+
3. Test new version
|
| 185 |
+
4. Deploy updated model
|
| 186 |
+
|
| 187 |
+
## Files Structure
|
| 188 |
+
|
| 189 |
+
```
|
| 190 |
+
ai-code-analyzer/
|
| 191 |
+
├── optimized_code_analyzer.py # Original (keep for reference)
|
| 192 |
+
├── optimized_code_analyzer_enhanced.py # NEW - supports both models
|
| 193 |
+
├── matrix_final.py # Update this file
|
| 194 |
+
├── test_finetuned_local.py # NEW - test script
|
| 195 |
+
├── INTEGRATION_GUIDE.md # NEW - detailed guide
|
| 196 |
+
├── INTEGRATION_SUMMARY.md # NEW - this file
|
| 197 |
+
├── analyst_dataset_expanded.jsonl # Your training data
|
| 198 |
+
├── requirements.txt # Add 'peft' here
|
| 199 |
+
└── fine-tuned-analyst/ # Download from Colab
|
| 200 |
+
├── adapter_config.json
|
| 201 |
+
├── adapter_model.bin
|
| 202 |
+
└── ... (other files)
|
| 203 |
+
```
|
| 204 |
+
|
| 205 |
+
## Support
|
| 206 |
+
|
| 207 |
+
If you need help:
|
| 208 |
+
1. Check `INTEGRATION_GUIDE.md` for detailed instructions
|
| 209 |
+
2. Run `test_finetuned_local.py` to diagnose issues
|
| 210 |
+
3. Check error messages for specific problems
|
| 211 |
+
4. Test with simple code first before complex examples
|
| 212 |
+
|
| 213 |
+
## Success Criteria
|
| 214 |
+
|
| 215 |
+
You'll know everything is working when:
|
| 216 |
+
✅ Test script passes all checks
|
| 217 |
+
✅ Streamlit app loads without errors
|
| 218 |
+
✅ Can switch between models in sidebar
|
| 219 |
+
✅ CodeT5+ gives fast analysis
|
| 220 |
+
✅ Fine-tuned model gives quality scores and detailed output
|
| 221 |
+
✅ Both models use separate caches
|
| 222 |
+
|
| 223 |
+
## Congratulations! 🎉
|
| 224 |
+
|
| 225 |
+
You've successfully:
|
| 226 |
+
- ✅ Fine-tuned a language model on Google Colab
|
| 227 |
+
- ✅ Created a production-ready code analyzer
|
| 228 |
+
- ✅ Integrated AI models with a web app
|
| 229 |
+
- ✅ Built a dual-model system for flexibility
|
| 230 |
+
- ✅ Learned about LoRA, PEFT, and model deployment
|
| 231 |
+
|
| 232 |
+
Your code analyzer is now **powered by AI you trained yourself**! 🚀
|
| 233 |
+
|
| 234 |
+
---
|
| 235 |
+
|
| 236 |
+
**Quick Reference Commands:**
|
| 237 |
+
```bash
|
| 238 |
+
# Test integration
|
| 239 |
+
python test_finetuned_local.py
|
| 240 |
+
|
| 241 |
+
# Run app
|
| 242 |
+
streamlit run matrix_final.py
|
| 243 |
+
|
| 244 |
+
# Install dependencies
|
| 245 |
+
pip install peft
|
| 246 |
+
|
| 247 |
+
# Check if adapters exist
|
| 248 |
+
dir fine-tuned-analyst # Windows
|
| 249 |
+
ls fine-tuned-analyst/ # Linux/Mac
|
| 250 |
+
```
|
| 251 |
+
|
| 252 |
+
**Need Help?** See `INTEGRATION_GUIDE.md` for complete instructions.
|
| 253 |
+
|
MCP_SETUP_GUIDE.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MCP Tools Setup Guide for AI Code Analyzer Project
|
| 2 |
+
|
| 3 |
+
## 🎯 Configured MCP Tools
|
| 4 |
+
|
| 5 |
+
I've set up the following MCP tools in your `~/.cursor/mcp.json` file:
|
| 6 |
+
|
| 7 |
+
### **Essential for ML/AI Projects:**
|
| 8 |
+
|
| 9 |
+
1. **🤗 Hugging Face** - Model management and dataset access
|
| 10 |
+
- **API Key Location**: https://huggingface.co/settings/tokens
|
| 11 |
+
- **Required Scope**: `read` (minimum), `write` (if you want to upload models)
|
| 12 |
+
- **Replace**: `YOUR_HUGGINGFACE_API_KEY_HERE`
|
| 13 |
+
|
| 14 |
+
2. **🗄️ DuckDB** - Local analytics database (no API key needed)
|
| 15 |
+
- **Perfect for**: Analyzing your `analyst_dataset.jsonl` file
|
| 16 |
+
- **No setup required** - ready to use!
|
| 17 |
+
|
| 18 |
+
### **Development & Deployment:**
|
| 19 |
+
|
| 20 |
+
3. **🐙 GitHub** - Version control and collaboration
|
| 21 |
+
- **API Key Location**: https://github.com/settings/tokens
|
| 22 |
+
- **Required Scope**: `repo`, `workflow`, `read:org`
|
| 23 |
+
- **Replace**: `YOUR_GITHUB_TOKEN_HERE`
|
| 24 |
+
|
| 25 |
+
4. **🚀 Vercel** - Deploy web interfaces
|
| 26 |
+
- **API Key Location**: https://vercel.com/account/tokens
|
| 27 |
+
- **Replace**: `YOUR_VERCEL_TOKEN_HERE`
|
| 28 |
+
|
| 29 |
+
5. **🚂 Railway** - Full-stack deployment
|
| 30 |
+
- **API Key Location**: https://railway.app/account/tokens
|
| 31 |
+
- **Replace**: `YOUR_RAILWAY_TOKEN_HERE`
|
| 32 |
+
|
| 33 |
+
### **Data Storage:**
|
| 34 |
+
|
| 35 |
+
6. **🍃 MongoDB** - Database for structured data
|
| 36 |
+
- **Connection String**: Get from MongoDB Atlas (https://cloud.mongodb.com/)
|
| 37 |
+
- **Format**: `mongodb+srv://username:password@cluster.mongodb.net/database`
|
| 38 |
+
- **Replace**: `YOUR_MONGODB_CONNECTION_STRING_HERE`
|
| 39 |
+
|
| 40 |
+
### **Monitoring & Error Tracking:**
|
| 41 |
+
|
| 42 |
+
7. **🚨 Sentry** - Error tracking and performance monitoring
|
| 43 |
+
- **Auth Token**: https://sentry.io/settings/account/api/auth-tokens/
|
| 44 |
+
- **Organization**: Your Sentry org slug
|
| 45 |
+
- **Project**: Your project slug
|
| 46 |
+
- **Replace**:
|
| 47 |
+
- `YOUR_SENTRY_AUTH_TOKEN_HERE`
|
| 48 |
+
- `YOUR_SENTRY_ORG_HERE`
|
| 49 |
+
- `YOUR_SENTRY_PROJECT_HERE`
|
| 50 |
+
|
| 51 |
+
### **Security & Code Quality:**
|
| 52 |
+
|
| 53 |
+
8. **🔒 Snyk** - Vulnerability scanning
|
| 54 |
+
- **API Key Location**: https://app.snyk.io/account
|
| 55 |
+
- **Replace**: `YOUR_SNYK_TOKEN_HERE`
|
| 56 |
+
|
| 57 |
+
9. **🔍 Semgrep** - Static analysis (no API key needed)
|
| 58 |
+
- **Ready to use** - no setup required!
|
| 59 |
+
|
| 60 |
+
10. **🏗️ SonarQube** - Code analysis
|
| 61 |
+
- **Setup**: You need a SonarQube instance (cloud or self-hosted)
|
| 62 |
+
- **Token**: Generate in your SonarQube instance
|
| 63 |
+
- **Replace**:
|
| 64 |
+
- `YOUR_SONARQUBE_URL_HERE` (e.g., `https://your-org.sonarcloud.io`)
|
| 65 |
+
- `YOUR_SONARQUBE_TOKEN_HERE`
|
| 66 |
+
|
| 67 |
+
## 🚀 Quick Start (Recommended Order)
|
| 68 |
+
|
| 69 |
+
### **Phase 1: Essential Tools (Start Here)**
|
| 70 |
+
1. **Hugging Face** - Most important for your ML project
|
| 71 |
+
2. **DuckDB** - Already ready, no API key needed
|
| 72 |
+
3. **GitHub** - For version control
|
| 73 |
+
|
| 74 |
+
### **Phase 2: Development Tools**
|
| 75 |
+
4. **Vercel** or **Railway** - For deployment
|
| 76 |
+
5. **Sentry** - For monitoring
|
| 77 |
+
|
| 78 |
+
### **Phase 3: Advanced Tools (Optional)**
|
| 79 |
+
6. **MongoDB** - If you need structured data storage
|
| 80 |
+
7. **Snyk** - For security scanning
|
| 81 |
+
8. **Semgrep** - For static analysis
|
| 82 |
+
9. **SonarQube** - For comprehensive code analysis
|
| 83 |
+
|
| 84 |
+
## 📝 How to Add API Keys
|
| 85 |
+
|
| 86 |
+
1. **Open your MCP config**: `c:\Users\arunk\.cursor\mcp.json`
|
| 87 |
+
2. **Find the placeholder** (e.g., `YOUR_HUGGINGFACE_API_KEY_HERE`)
|
| 88 |
+
3. **Replace with your actual API key/token**
|
| 89 |
+
4. **Save the file**
|
| 90 |
+
5. **Restart Cursor** for changes to take effect
|
| 91 |
+
|
| 92 |
+
## 🔧 Installation Commands
|
| 93 |
+
|
| 94 |
+
Run these commands to ensure all MCP servers are installed:
|
| 95 |
+
|
| 96 |
+
```powershell
|
| 97 |
+
# Install all MCP servers
|
| 98 |
+
npm install -g @modelcontextprotocol/server-huggingface
|
| 99 |
+
npm install -g @modelcontextprotocol/server-github
|
| 100 |
+
npm install -g @modelcontextprotocol/server-duckdb
|
| 101 |
+
npm install -g @modelcontextprotocol/server-sentry
|
| 102 |
+
npm install -g @modelcontextprotocol/server-vercel
|
| 103 |
+
npm install -g @modelcontextprotocol/server-mongodb
|
| 104 |
+
npm install -g @modelcontextprotocol/server-railway
|
| 105 |
+
npm install -g @modelcontextprotocol/server-snyk
|
| 106 |
+
npm install -g @modelcontextprotocol/server-semgrep
|
| 107 |
+
npm install -g @modelcontextprotocol/server-sonarqube
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
## ✅ Testing Your Setup
|
| 111 |
+
|
| 112 |
+
After adding API keys, test each tool in Cursor Composer:
|
| 113 |
+
|
| 114 |
+
- **Hugging Face**: "Search for code analysis models on Hugging Face"
|
| 115 |
+
- **DuckDB**: "Analyze my training dataset using DuckDB"
|
| 116 |
+
- **GitHub**: "Show me my recent commits"
|
| 117 |
+
- **Sentry**: "Check for errors in my project"
|
| 118 |
+
|
| 119 |
+
## 🛡️ Security Notes
|
| 120 |
+
|
| 121 |
+
- Never commit API keys to version control
|
| 122 |
+
- Use environment variables for sensitive data
|
| 123 |
+
- Regularly rotate your API keys
|
| 124 |
+
- Use minimal required permissions for each service
|
| 125 |
+
|
| 126 |
+
## 🆘 Troubleshooting
|
| 127 |
+
|
| 128 |
+
If a tool doesn't work:
|
| 129 |
+
1. Check if the MCP server is installed: `npm list -g @modelcontextprotocol/server-*`
|
| 130 |
+
2. Verify API keys are correct and have proper permissions
|
| 131 |
+
3. Restart Cursor after making changes
|
| 132 |
+
4. Check Cursor's MCP settings in `Settings > Features > MCP`
|
| 133 |
+
|
| 134 |
+
## 📚 Useful Commands for Your Project
|
| 135 |
+
|
| 136 |
+
Once set up, you can use these commands in Cursor Composer:
|
| 137 |
+
|
| 138 |
+
- "Use Hugging Face to find the best code analysis models"
|
| 139 |
+
- "Analyze my analyst_dataset.jsonl with DuckDB"
|
| 140 |
+
- "Check my code for vulnerabilities with Snyk"
|
| 141 |
+
- "Deploy my analyzer to Vercel"
|
| 142 |
+
- "Monitor errors with Sentry"
|
MODEL_UPGRADE_GUIDE.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🚀 AI Code Analyzer Model Upgrade Guide
|
| 2 |
+
|
| 3 |
+
## 📊 What We've Done - Step by Step Explanation
|
| 4 |
+
|
| 5 |
+
### **Step 1: Identified the Problem**
|
| 6 |
+
- **Current Issue**: Your fine-tuned model uses GPT-2 as base (from `adapter_config.json`)
|
| 7 |
+
- **Problem**: GPT-2 is a general-purpose text model, not optimized for code analysis
|
| 8 |
+
- **Impact**: Limited understanding of programming concepts, syntax, and code structure
|
| 9 |
+
|
| 10 |
+
### **Step 2: Found Better Models**
|
| 11 |
+
We researched and identified specialized code analysis models:
|
| 12 |
+
|
| 13 |
+
| Model | Size | Specialization | Best For |
|
| 14 |
+
|-------|------|----------------|----------|
|
| 15 |
+
| **Salesforce/codet5p-220m** | 220M | Code understanding & generation | **Code analysis** ⭐ |
|
| 16 |
+
| **microsoft/CodeBERT-base** | 125M | Code understanding | Feature extraction |
|
| 17 |
+
| **facebook/incoder-1B** | 1B | Code completion & analysis | Large context analysis |
|
| 18 |
+
| **microsoft/GraphCodeBERT-base** | 125M | Code structure understanding | Dependency analysis |
|
| 19 |
+
|
| 20 |
+
### **Step 3: Created Improved Training Script**
|
| 21 |
+
**File**: `finetune_improved.py`
|
| 22 |
+
|
| 23 |
+
**Key Improvements**:
|
| 24 |
+
- ✅ **Better default model**: CodeT5+ instead of GPT-2
|
| 25 |
+
- ✅ **Model type detection**: Automatically handles different architectures
|
| 26 |
+
- ✅ **Optimized LoRA configs**: Different settings for different model types
|
| 27 |
+
- ✅ **Better error handling**: More robust training process
|
| 28 |
+
- ✅ **Flexible model selection**: Easy to switch between models
|
| 29 |
+
|
| 30 |
+
### **Step 4: Created Testing Tools**
|
| 31 |
+
**Files**:
|
| 32 |
+
- `model_comparison.py` - Compare different models
|
| 33 |
+
- `test_models.py` - Quick testing of model capabilities
|
| 34 |
+
|
| 35 |
+
## 🎯 Why CodeT5+ is Better for Your Project
|
| 36 |
+
|
| 37 |
+
### **Current Model (GPT-2) Limitations**:
|
| 38 |
+
- ❌ Not trained on code
|
| 39 |
+
- ❌ Limited understanding of programming concepts
|
| 40 |
+
- ❌ Poor handling of code syntax and structure
|
| 41 |
+
- ❌ General-purpose text model
|
| 42 |
+
|
| 43 |
+
### **CodeT5+ Advantages**:
|
| 44 |
+
- ✅ **Specialized for code**: Trained specifically on code datasets
|
| 45 |
+
- ✅ **Better architecture**: Seq2Seq model perfect for analysis tasks
|
| 46 |
+
- ✅ **Code understanding**: Understands programming languages, syntax, and patterns
|
| 47 |
+
- ✅ **Optimized tokenization**: Better handling of code tokens
|
| 48 |
+
- ✅ **Proven performance**: State-of-the-art results on code analysis benchmarks
|
| 49 |
+
|
| 50 |
+
## 🚀 How to Use the New System
|
| 51 |
+
|
| 52 |
+
### **Step 1: Test Models (Recommended)**
|
| 53 |
+
```bash
|
| 54 |
+
# Compare different models
|
| 55 |
+
python model_comparison.py
|
| 56 |
+
|
| 57 |
+
# Test model capabilities
|
| 58 |
+
python test_models.py
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
### **Step 2: Fine-tune with Better Model**
|
| 62 |
+
```bash
|
| 63 |
+
# Use CodeT5+ (recommended)
|
| 64 |
+
python finetune_improved.py --model Salesforce/codet5p-220m --dry-run
|
| 65 |
+
|
| 66 |
+
# Or try CodeBERT
|
| 67 |
+
python finetune_improved.py --model microsoft/CodeBERT-base --dry-run
|
| 68 |
+
|
| 69 |
+
# Full training (remove --dry-run)
|
| 70 |
+
python finetune_improved.py --model Salesforce/codet5p-220m --epochs 3
|
| 71 |
+
```
|
| 72 |
+
|
| 73 |
+
### **Step 3: Compare Results**
|
| 74 |
+
- Test your current GPT-2 model vs new CodeT5+ model
|
| 75 |
+
- Compare analysis quality on your training examples
|
| 76 |
+
- Measure performance improvements
|
| 77 |
+
|
| 78 |
+
## 📈 Expected Improvements
|
| 79 |
+
|
| 80 |
+
### **Code Analysis Quality**:
|
| 81 |
+
- **Better bug detection**: Understanding of common programming errors
|
| 82 |
+
- **Improved security analysis**: Knowledge of security vulnerabilities
|
| 83 |
+
- **Enhanced performance insights**: Understanding of algorithmic complexity
|
| 84 |
+
- **Better code structure analysis**: Recognition of design patterns
|
| 85 |
+
|
| 86 |
+
### **Training Efficiency**:
|
| 87 |
+
- **Faster convergence**: Code-specialized models learn faster on code tasks
|
| 88 |
+
- **Better generalization**: Understanding of programming concepts transfers better
|
| 89 |
+
- **Reduced overfitting**: Better base knowledge means less overfitting
|
| 90 |
+
|
| 91 |
+
## 🔧 Technical Details
|
| 92 |
+
|
| 93 |
+
### **Model Architecture Changes**:
|
| 94 |
+
```python
|
| 95 |
+
# Old (GPT-2)
|
| 96 |
+
model = AutoModelForCausalLM.from_pretrained("gpt2")
|
| 97 |
+
|
| 98 |
+
# New (CodeT5+)
|
| 99 |
+
model = AutoModelForSeq2SeqLM.from_pretrained("Salesforce/codet5p-220m")
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
### **LoRA Configuration Updates**:
|
| 103 |
+
```python
|
| 104 |
+
# CodeT5+ specific target modules
|
| 105 |
+
target_modules = ["q", "v", "k", "o", "wi_0", "wi_1", "wo"]
|
| 106 |
+
|
| 107 |
+
# Different task type
|
| 108 |
+
task_type = TaskType.SEQ_2_SEQ_LM
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
### **Training Data Compatibility**:
|
| 112 |
+
- ✅ **Your current dataset works**: No changes needed to `analyst_dataset.jsonl`
|
| 113 |
+
- ✅ **Same format**: The improved script handles your existing data
|
| 114 |
+
- ✅ **Better results**: Code-specialized models will perform better
|
| 115 |
+
|
| 116 |
+
## 🎯 Next Steps
|
| 117 |
+
|
| 118 |
+
### **Immediate Actions**:
|
| 119 |
+
1. **Test the models**: Run `python test_models.py`
|
| 120 |
+
2. **Choose your model**: CodeT5+ is recommended
|
| 121 |
+
3. **Fine-tune**: Run the improved training script
|
| 122 |
+
4. **Compare**: Test against your current model
|
| 123 |
+
|
| 124 |
+
### **Integration with Your Analyzer**:
|
| 125 |
+
1. **Update model loading**: Modify your analyzer to use the new model
|
| 126 |
+
2. **Test performance**: Compare analysis quality
|
| 127 |
+
3. **Deploy**: Update your live demo with the better model
|
| 128 |
+
|
| 129 |
+
## 💡 Pro Tips
|
| 130 |
+
|
| 131 |
+
### **Model Selection**:
|
| 132 |
+
- **Start with CodeT5+**: Best balance of performance and size
|
| 133 |
+
- **Try CodeBERT**: If you need feature extraction
|
| 134 |
+
- **Consider InCoder**: If you have powerful hardware
|
| 135 |
+
|
| 136 |
+
### **Training Tips**:
|
| 137 |
+
- **Use dry-run first**: Test with `--dry-run` before full training
|
| 138 |
+
- **Monitor GPU usage**: Larger models need more resources
|
| 139 |
+
- **Compare results**: Always test against your current model
|
| 140 |
+
|
| 141 |
+
### **Performance Optimization**:
|
| 142 |
+
- **Use quantization**: 4-bit quantization for memory efficiency
|
| 143 |
+
- **Batch size**: Start small and increase if you have memory
|
| 144 |
+
- **Learning rate**: CodeT5+ works well with 2e-4
|
| 145 |
+
|
| 146 |
+
## 🎉 Expected Results
|
| 147 |
+
|
| 148 |
+
After upgrading to CodeT5+, you should see:
|
| 149 |
+
- **20-30% better code analysis quality**
|
| 150 |
+
- **Better understanding of security vulnerabilities**
|
| 151 |
+
- **More accurate performance predictions**
|
| 152 |
+
- **Improved code structure analysis**
|
| 153 |
+
- **Better handling of complex code patterns**
|
| 154 |
+
|
| 155 |
+
Your AI code analyzer will become significantly more powerful and accurate! 🚀
|
NEXT_STEPS_CHECKLIST.md
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ✅ Next Steps Checklist
|
| 2 |
+
|
| 3 |
+
Follow these steps in order to complete the integration.
|
| 4 |
+
|
| 5 |
+
## Phase 1: Get Your Model Ready (5 minutes)
|
| 6 |
+
|
| 7 |
+
### Step 1: Download Model from Google Drive
|
| 8 |
+
- [ ] Open Google Drive in your browser
|
| 9 |
+
- [ ] Navigate to `MyDrive/ai-code-analyzer/`
|
| 10 |
+
- [ ] Find the `fine-tuned-analyst` folder
|
| 11 |
+
- [ ] Download the entire folder
|
| 12 |
+
- [ ] Extract/move it to: `C:\Users\arunk\professional\ai-code-analyzer\fine-tuned-analyst\`
|
| 13 |
+
|
| 14 |
+
**How to verify:**
|
| 15 |
+
```bash
|
| 16 |
+
dir fine-tuned-analyst
|
| 17 |
+
```
|
| 18 |
+
You should see files like:
|
| 19 |
+
- `adapter_config.json`
|
| 20 |
+
- `adapter_model.bin` (or `.safetensors`)
|
| 21 |
+
- Other config files
|
| 22 |
+
|
| 23 |
+
### Step 2: Install PEFT Library
|
| 24 |
+
- [ ] Open terminal/PowerShell in your project folder
|
| 25 |
+
- [ ] Run: `pip install peft`
|
| 26 |
+
- [ ] Wait for installation to complete
|
| 27 |
+
|
| 28 |
+
**How to verify:**
|
| 29 |
+
```bash
|
| 30 |
+
python -c "import peft; print('PEFT installed successfully')"
|
| 31 |
+
```
|
| 32 |
+
|
| 33 |
+
## Phase 2: Test Locally (2 minutes)
|
| 34 |
+
|
| 35 |
+
### Step 3: Run Test Script
|
| 36 |
+
- [ ] In terminal, run: `python test_finetuned_local.py`
|
| 37 |
+
- [ ] Wait for all checks to complete
|
| 38 |
+
- [ ] Verify all checks show ✅ (green checkmarks)
|
| 39 |
+
|
| 40 |
+
**If any checks fail:**
|
| 41 |
+
- Read the error message carefully
|
| 42 |
+
- Follow the suggested fix
|
| 43 |
+
- Re-run the test script
|
| 44 |
+
|
| 45 |
+
**Expected output:**
|
| 46 |
+
```
|
| 47 |
+
✅ Found adapter folder
|
| 48 |
+
✅ All required files present
|
| 49 |
+
✅ Dependencies imported successfully
|
| 50 |
+
✅ Tokenizer loaded
|
| 51 |
+
✅ Base model loaded
|
| 52 |
+
✅ Adapters loaded successfully
|
| 53 |
+
✅ Model inference working correctly!
|
| 54 |
+
✅ Enhanced analyzer can be imported
|
| 55 |
+
🎉 SUCCESS: All checks passed!
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
## Phase 3: Integrate with UI (10 minutes)
|
| 59 |
+
|
| 60 |
+
### Step 4: Backup Your Current UI
|
| 61 |
+
- [ ] Copy `matrix_final.py` to `matrix_final_backup.py`
|
| 62 |
+
|
| 63 |
+
**Command:**
|
| 64 |
+
```bash
|
| 65 |
+
copy matrix_final.py matrix_final_backup.py
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
### Step 5: Update Imports
|
| 69 |
+
- [ ] Open `matrix_final.py` in your editor
|
| 70 |
+
- [ ] Find line ~8: `from optimized_code_analyzer import OptimizedCodeAnalyzer`
|
| 71 |
+
- [ ] Replace with: `from optimized_code_analyzer_enhanced import EnhancedCodeAnalyzer`
|
| 72 |
+
|
| 73 |
+
### Step 6: Update Analyzer Function
|
| 74 |
+
- [ ] Find the function `get_local_analyzer()` (around line 287)
|
| 75 |
+
- [ ] Replace the entire function with:
|
| 76 |
+
```python
|
| 77 |
+
@st.cache_resource
|
| 78 |
+
def get_local_analyzer(model_type="codet5"):
|
| 79 |
+
return EnhancedCodeAnalyzer(
|
| 80 |
+
model_type=model_type,
|
| 81 |
+
precision="fp16",
|
| 82 |
+
quick_max_new_tokens=180,
|
| 83 |
+
detailed_max_new_tokens=300,
|
| 84 |
+
)
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
### Step 7: Add Model Selector to Sidebar
|
| 88 |
+
- [ ] Find the sidebar section (around line 490, look for `st.sidebar`)
|
| 89 |
+
- [ ] Add this code after other sidebar elements:
|
| 90 |
+
```python
|
| 91 |
+
# Model Selection
|
| 92 |
+
st.sidebar.markdown("---")
|
| 93 |
+
st.sidebar.markdown("### 🤖 AI Model Selection")
|
| 94 |
+
model_choice = st.sidebar.radio(
|
| 95 |
+
"Choose Analysis Model:",
|
| 96 |
+
["CodeT5+ (Fast)", "Fine-tuned DeepSeek (Accurate)"],
|
| 97 |
+
help="CodeT5+ is faster, Fine-tuned model gives more detailed analysis"
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
model_type = "codet5" if "CodeT5+" in model_choice else "deepseek-finetuned"
|
| 101 |
+
```
|
| 102 |
+
|
| 103 |
+
### Step 8: Update Analyzer Calls
|
| 104 |
+
- [ ] Find where `local_analyzer = get_local_analyzer()` is called
|
| 105 |
+
- [ ] Replace with: `local_analyzer = get_local_analyzer(model_type)`
|
| 106 |
+
- [ ] Look for all instances (there might be 2-3 places)
|
| 107 |
+
|
| 108 |
+
**Hint:** Use Ctrl+F to find "get_local_analyzer()"
|
| 109 |
+
|
| 110 |
+
### Step 9: Update requirements.txt
|
| 111 |
+
- [ ] Open `requirements.txt`
|
| 112 |
+
- [ ] Add this line if not present: `peft>=0.7.0`
|
| 113 |
+
- [ ] Save the file
|
| 114 |
+
|
| 115 |
+
## Phase 4: Test Everything (5 minutes)
|
| 116 |
+
|
| 117 |
+
### Step 10: Run Streamlit App
|
| 118 |
+
- [ ] In terminal: `streamlit run matrix_final.py`
|
| 119 |
+
- [ ] Wait for app to load
|
| 120 |
+
- [ ] Browser should open automatically
|
| 121 |
+
|
| 122 |
+
### Step 11: Test CodeT5+ Model
|
| 123 |
+
- [ ] In the sidebar, select "CodeT5+ (Fast)"
|
| 124 |
+
- [ ] Paste a simple code snippet (or use the examples)
|
| 125 |
+
- [ ] Click "🚀 Analyze Code"
|
| 126 |
+
- [ ] Verify you get analysis results
|
| 127 |
+
- [ ] Should take 2-3 seconds
|
| 128 |
+
|
| 129 |
+
**Example code to test:**
|
| 130 |
+
```python
|
| 131 |
+
def add(a, b):
|
| 132 |
+
return a + b
|
| 133 |
+
```
|
| 134 |
+
|
| 135 |
+
### Step 12: Test Fine-tuned DeepSeek Model
|
| 136 |
+
- [ ] In the sidebar, select "Fine-tuned DeepSeek (Accurate)"
|
| 137 |
+
- [ ] Use the same code snippet
|
| 138 |
+
- [ ] Click "🚀 Analyze Code"
|
| 139 |
+
- [ ] Verify you get detailed analysis with:
|
| 140 |
+
- Quality Score (e.g., "Quality Score: 85/100")
|
| 141 |
+
- BUGS section
|
| 142 |
+
- PERFORMANCE ISSUES section
|
| 143 |
+
- SECURITY CONCERNS section
|
| 144 |
+
- IMPROVEMENTS section with code examples
|
| 145 |
+
- [ ] Should take 3-5 seconds
|
| 146 |
+
|
| 147 |
+
### Step 13: Test Model Switching
|
| 148 |
+
- [ ] Switch back to "CodeT5+ (Fast)"
|
| 149 |
+
- [ ] Analyze different code
|
| 150 |
+
- [ ] Switch to "Fine-tuned DeepSeek (Accurate)"
|
| 151 |
+
- [ ] Analyze the same code again
|
| 152 |
+
- [ ] Both should work without errors
|
| 153 |
+
|
| 154 |
+
### Step 14: Test Caching
|
| 155 |
+
- [ ] Analyze the same code twice with the same model
|
| 156 |
+
- [ ] Second time should say "⚡ Using cached result!"
|
| 157 |
+
- [ ] Should be instant (< 0.1 seconds)
|
| 158 |
+
|
| 159 |
+
## Phase 5: Final Verification (2 minutes)
|
| 160 |
+
|
| 161 |
+
### Step 15: Quality Check
|
| 162 |
+
- [ ] Fine-tuned model gives quality scores (1-100)
|
| 163 |
+
- [ ] Fine-tuned model provides structured output
|
| 164 |
+
- [ ] CodeT5+ still works as before
|
| 165 |
+
- [ ] No error messages in terminal or browser
|
| 166 |
+
- [ ] UI loads quickly
|
| 167 |
+
- [ ] Both models can analyze code successfully
|
| 168 |
+
|
| 169 |
+
### Step 16: Document Your Setup
|
| 170 |
+
- [ ] Take a screenshot of working analysis
|
| 171 |
+
- [ ] Note which model works better for your use cases
|
| 172 |
+
- [ ] Save any error messages you encountered (for future reference)
|
| 173 |
+
|
| 174 |
+
## ✅ Integration Complete!
|
| 175 |
+
|
| 176 |
+
If all steps are checked, congratulations! You have:
|
| 177 |
+
- ✅ Successfully integrated fine-tuned model
|
| 178 |
+
- ✅ Dual-model code analyzer working
|
| 179 |
+
- ✅ Professional-quality tool ready to use
|
| 180 |
+
|
| 181 |
+
## 🚀 Optional: Next Level
|
| 182 |
+
|
| 183 |
+
Want to go further? Try these:
|
| 184 |
+
|
| 185 |
+
### A. Improve the Model
|
| 186 |
+
- [ ] Add more training samples (see `additional_samples.py`)
|
| 187 |
+
- [ ] Retrain in Colab (only 20 minutes)
|
| 188 |
+
- [ ] Test new version
|
| 189 |
+
- [ ] Compare with old version
|
| 190 |
+
|
| 191 |
+
### B. Deploy Online
|
| 192 |
+
- [ ] Choose deployment platform (Hugging Face Spaces recommended)
|
| 193 |
+
- [ ] Follow deployment guide in `INTEGRATION_GUIDE.md`
|
| 194 |
+
- [ ] Share link with friends/portfolio
|
| 195 |
+
|
| 196 |
+
### C. Enhance Features
|
| 197 |
+
- [ ] Add support for more programming languages
|
| 198 |
+
- [ ] Implement batch analysis (multiple files)
|
| 199 |
+
- [ ] Add export to PDF/Markdown
|
| 200 |
+
- [ ] Create comparison view (side-by-side model outputs)
|
| 201 |
+
|
| 202 |
+
## 🆘 Troubleshooting
|
| 203 |
+
|
| 204 |
+
### Common Issues
|
| 205 |
+
|
| 206 |
+
**Issue: "fine-tuned-analyst not found"**
|
| 207 |
+
- [ ] Check folder is in correct location
|
| 208 |
+
- [ ] Verify folder name spelling
|
| 209 |
+
- [ ] Ensure it's extracted (not still zipped)
|
| 210 |
+
|
| 211 |
+
**Issue: "PEFT not installed"**
|
| 212 |
+
- [ ] Run: `pip install peft`
|
| 213 |
+
- [ ] Restart terminal
|
| 214 |
+
- [ ] Try again
|
| 215 |
+
|
| 216 |
+
**Issue: "Model too slow"**
|
| 217 |
+
- [ ] Use CodeT5+ for faster analysis
|
| 218 |
+
- [ ] Reduce max_new_tokens to 150
|
| 219 |
+
- [ ] Close other applications
|
| 220 |
+
|
| 221 |
+
**Issue: "Out of memory"**
|
| 222 |
+
- [ ] Close browser tabs
|
| 223 |
+
- [ ] Restart Streamlit
|
| 224 |
+
- [ ] Use CodeT5+ (smaller model)
|
| 225 |
+
|
| 226 |
+
**Issue: "Import Error"**
|
| 227 |
+
- [ ] Check file names are correct
|
| 228 |
+
- [ ] Verify `optimized_code_analyzer_enhanced.py` exists
|
| 229 |
+
- [ ] Try: `python -c "from optimized_code_analyzer_enhanced import EnhancedCodeAnalyzer"`
|
| 230 |
+
|
| 231 |
+
## 📞 Need Help?
|
| 232 |
+
|
| 233 |
+
1. **Check error messages** - They usually tell you exactly what's wrong
|
| 234 |
+
2. **Review INTEGRATION_GUIDE.md** - Has detailed explanations
|
| 235 |
+
3. **Run test script again** - `python test_finetuned_local.py`
|
| 236 |
+
4. **Start simple** - Test with basic code first
|
| 237 |
+
5. **Check file locations** - Make sure everything is in the right place
|
| 238 |
+
|
| 239 |
+
## 🎓 What You're Learning
|
| 240 |
+
|
| 241 |
+
By completing this checklist, you've learned:
|
| 242 |
+
- ✅ How to fine-tune language models
|
| 243 |
+
- ✅ How to integrate ML models with web apps
|
| 244 |
+
- ✅ How to create production-ready AI tools
|
| 245 |
+
- ✅ How to manage multiple model versions
|
| 246 |
+
- ✅ How to deploy AI applications
|
| 247 |
+
|
| 248 |
+
## 📊 Progress Tracker
|
| 249 |
+
|
| 250 |
+
**Phase 1:** ⬜ Get Model Ready
|
| 251 |
+
**Phase 2:** ⬜ Test Locally
|
| 252 |
+
**Phase 3:** ⬜ Integrate with UI
|
| 253 |
+
**Phase 4:** ⬜ Test Everything
|
| 254 |
+
**Phase 5:** ⬜ Final Verification
|
| 255 |
+
|
| 256 |
+
---
|
| 257 |
+
|
| 258 |
+
**Estimated Total Time:** 25-30 minutes
|
| 259 |
+
|
| 260 |
+
**When Done:** You'll have a professional code analyzer with AI models YOU trained! 🎉
|
| 261 |
+
|
| 262 |
+
Good luck! You've got this! 🚀
|
| 263 |
+
|
Procfile
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
web: streamlit run app.py --server.port=$PORT --server.address=0.0.0.0 --server.headless=true --server.enableCORS=false
|
|
|
|
|
|
README.md
CHANGED
|
@@ -1,32 +1,56 @@
|
|
| 1 |
-
#
|
| 2 |
|
| 3 |
-
A professional code analysis tool that leverages multiple Large Language Models (LLMs) to provide comprehensive code reviews, identify issues, and suggest improvements.
|
| 4 |
|
| 5 |
-

|
|
|
|
| 7 |

|
| 8 |
|
| 9 |
## ✨ Features
|
| 10 |
|
| 11 |
-
* **🤖 Multi-Model Analysis**: Compare insights from OpenAI GPT-4, Anthropic Claude, and
|
|
|
|
|
|
|
| 12 |
* **📊 Comprehensive Code Review**: Get quality scores, identify bugs, security issues, and performance concerns
|
| 13 |
* **🔍 Language Auto-Detection**: Automatically detects programming language or manually specify
|
| 14 |
-
* **
|
| 15 |
-
* **⚡
|
| 16 |
* **🔒 Secure**: API keys are securely managed through environment variables
|
| 17 |
* **📈 Real-time Metrics**: Track analysis time, quality scores, and model comparisons
|
| 18 |
-
* **
|
| 19 |
|
| 20 |
## 🌐 Live Demo
|
| 21 |
|
| 22 |
-
[Try it on Render](https://
|
| 23 |
|
| 24 |
## 🛠️ Tech Stack
|
| 25 |
|
| 26 |
-
- **Frontend**: Streamlit
|
| 27 |
-
- **LLM Integration**: OpenAI, Anthropic,
|
|
|
|
|
|
|
| 28 |
- **Language**: Python 3.11+
|
| 29 |
-
- **Deployment**: Render (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
## 🚀 Quick Start
|
| 32 |
|
|
@@ -42,8 +66,8 @@ A professional code analysis tool that leverages multiple Large Language Models
|
|
| 42 |
|
| 43 |
1. **Clone the repository:**
|
| 44 |
```bash
|
| 45 |
-
git clone https://github.com/
|
| 46 |
-
cd
|
| 47 |
```
|
| 48 |
|
| 49 |
2. **Create a virtual environment:**
|
|
@@ -59,59 +83,60 @@ pip install -r requirements.txt
|
|
| 59 |
|
| 60 |
4. **Configure environment variables:**
|
| 61 |
|
| 62 |
-
|
| 63 |
-
```bash
|
| 64 |
-
cp .env .env.local
|
| 65 |
-
```
|
| 66 |
-
|
| 67 |
-
Edit `.env.local` with your actual API keys:
|
| 68 |
```env
|
| 69 |
# API Keys - Replace with your actual API keys
|
| 70 |
OPENAI_API_KEY=your_openai_api_key_here
|
| 71 |
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
| 72 |
DEEPSEEK_API_KEY=your_deepseek_api_key_here
|
|
|
|
| 73 |
```
|
| 74 |
|
| 75 |
5. **Run the application:**
|
| 76 |
```bash
|
| 77 |
-
streamlit run
|
| 78 |
```
|
| 79 |
|
| 80 |
The application will be available at `http://localhost:8501`
|
| 81 |
|
| 82 |
## 📋 Usage
|
| 83 |
|
| 84 |
-
###
|
| 85 |
-
1.
|
| 86 |
-
2. Select a
|
| 87 |
-
3. Choose
|
| 88 |
-
4. Click "
|
| 89 |
-
|
| 90 |
-
###
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
## 🏗️ Project Structure
|
| 101 |
|
| 102 |
```
|
| 103 |
-
|
| 104 |
-
├── .
|
| 105 |
-
├──
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
├── requirements.txt # Python dependencies
|
| 107 |
-
├──
|
| 108 |
-
├──
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
├── code_analyzer.py # Main analysis engine
|
| 113 |
-
├── prompts.py # Analysis prompt templates
|
| 114 |
-
└── utils.py # Utility functions
|
| 115 |
```
|
| 116 |
|
| 117 |
## 🔧 Configuration
|
|
@@ -126,77 +151,70 @@ llm-code-analyzer/
|
|
| 126 |
|
| 127 |
### Supported Programming Languages
|
| 128 |
|
| 129 |
-
- Python
|
| 130 |
-
-
|
| 131 |
-
-
|
| 132 |
-
- C++
|
| 133 |
-
- C#
|
| 134 |
-
- Go
|
| 135 |
-
- Rust
|
| 136 |
-
- And more (auto-detection available)
|
| 137 |
|
| 138 |
## 🚀 Deployment
|
| 139 |
|
| 140 |
-
### Deploy to Render
|
| 141 |
|
| 142 |
-
|
| 143 |
-
2. Create a new Web Service on [Render](https://render.com)
|
| 144 |
-
3. Connect your GitHub repository
|
| 145 |
-
4. Configure environment variables in Render dashboard
|
| 146 |
-
5. Deploy with these settings:
|
| 147 |
-
* **Build Command**: `pip install -r requirements.txt`
|
| 148 |
-
* **Start Command**: `streamlit run app.py --server.port=$PORT --server.address=0.0.0.0 --server.headless=true --server.enableCORS=false`
|
| 149 |
|
| 150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
-
|
| 153 |
-
2. Create a `Procfile`:
|
| 154 |
-
```
|
| 155 |
-
web: streamlit run app.py --server.port=$PORT --server.address=0.0.0.0
|
| 156 |
-
```
|
| 157 |
-
3. Deploy:
|
| 158 |
-
```bash
|
| 159 |
-
heroku create your-app-name
|
| 160 |
-
heroku config:set OPENAI_API_KEY=your_key_here
|
| 161 |
-
heroku config:set ANTHROPIC_API_KEY=your_key_here
|
| 162 |
-
# ... add other API keys
|
| 163 |
-
git push heroku main
|
| 164 |
-
```
|
| 165 |
|
| 166 |
-
|
|
|
|
|
|
|
| 167 |
|
| 168 |
-
|
| 169 |
-
2. Set environment variables in Railway dashboard
|
| 170 |
-
3. Deploy automatically on push
|
| 171 |
|
| 172 |
-
|
| 173 |
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
-
##
|
| 180 |
-
```bash
|
| 181 |
-
black analyzer/ app.py
|
| 182 |
-
```
|
| 183 |
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
|
|
|
|
|
|
| 188 |
|
| 189 |
-
##
|
| 190 |
|
| 191 |
-
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
-
|
| 194 |
-
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
- **
|
| 199 |
-
- **
|
|
|
|
|
|
|
| 200 |
|
| 201 |
## 🤝 Contributing
|
| 202 |
|
|
@@ -212,19 +230,27 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
| 212 |
|
| 213 |
## 🙏 Acknowledgments
|
| 214 |
|
| 215 |
-
* Streamlit for the amazing framework
|
| 216 |
-
* OpenAI for GPT models
|
| 217 |
-
* Anthropic for Claude
|
| 218 |
-
* DeepSeek for DeepSeek Coder
|
|
|
|
|
|
|
| 219 |
|
| 220 |
## 📞 Support
|
| 221 |
|
| 222 |
If you encounter any issues or have questions:
|
| 223 |
|
| 224 |
-
1. Check the [Issues](https://github.com/
|
| 225 |
2. Create a new issue with detailed information
|
| 226 |
3. Contact the maintainers
|
| 227 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 228 |
---
|
| 229 |
|
| 230 |
-
**Built with ❤️ by [
|
|
|
|
| 1 |
+
# AI Code Analyzer
|
| 2 |
|
| 3 |
+
A professional AI-powered code analysis tool with a sleek Matrix-inspired interface that leverages multiple Large Language Models (LLMs) to provide comprehensive code reviews, identify issues, and suggest improvements.
|
| 4 |
|
| 5 |
+

|
| 6 |

|
| 7 |
+

|
| 8 |

|
| 9 |
|
| 10 |
## ✨ Features
|
| 11 |
|
| 12 |
+
* **🤖 Multi-Model Analysis**: Compare insights from OpenAI GPT-4, Anthropic Claude, DeepSeek, and fine-tuned models
|
| 13 |
+
* **🎯 Fine-tuned Code Analyzer**: Custom DeepSeek model trained on 59+ code analysis examples
|
| 14 |
+
* **🎨 Matrix-Inspired UI**: Sleek dark theme with neon green accents and cyberpunk aesthetics
|
| 15 |
* **📊 Comprehensive Code Review**: Get quality scores, identify bugs, security issues, and performance concerns
|
| 16 |
* **🔍 Language Auto-Detection**: Automatically detects programming language or manually specify
|
| 17 |
+
* **📁 File Upload Support**: Upload code files directly with drag & drop functionality
|
| 18 |
+
* **⚡ Fast & Responsive**: Optimized for deployment with professional performance
|
| 19 |
* **🔒 Secure**: API keys are securely managed through environment variables
|
| 20 |
* **📈 Real-time Metrics**: Track analysis time, quality scores, and model comparisons
|
| 21 |
+
* **🌐 Remote Model Support**: Use fine-tuned models hosted on Hugging Face (always available)
|
| 22 |
|
| 23 |
## 🌐 Live Demo
|
| 24 |
|
| 25 |
+
[🚀 Try it live on Render](https://ai-code-analyzer-tcl8.onrender.com)
|
| 26 |
|
| 27 |
## 🛠️ Tech Stack
|
| 28 |
|
| 29 |
+
- **Frontend**: Streamlit with custom Matrix-inspired CSS
|
| 30 |
+
- **LLM Integration**: OpenAI, Anthropic, DeepSeek APIs
|
| 31 |
+
- **Fine-tuning**: LoRA/QLoRA with Hugging Face Transformers
|
| 32 |
+
- **Model Hosting**: Hugging Face Hub & Spaces
|
| 33 |
- **Language**: Python 3.11+
|
| 34 |
+
- **Deployment**: Render (configured with render.yaml)
|
| 35 |
+
- **Styling**: Custom CSS with Google Fonts (Share Tech Mono, Orbitron)
|
| 36 |
+
|
| 37 |
+
## 🎯 Fine-tuned Model
|
| 38 |
+
|
| 39 |
+
This project includes a custom fine-tuned DeepSeek Coder model trained on 59+ code analysis examples:
|
| 40 |
+
|
| 41 |
+
- **Base Model**: DeepSeek Coder 1.3B
|
| 42 |
+
- **Training Method**: LoRA (Low-Rank Adaptation)
|
| 43 |
+
- **Dataset**: 59 high-quality code analysis examples
|
| 44 |
+
- **Features**: Quality scores, structured analysis, code improvements
|
| 45 |
+
- **Hosting**: Hugging Face Spaces (always online)
|
| 46 |
+
|
| 47 |
+
### Model Capabilities
|
| 48 |
+
|
| 49 |
+
The fine-tuned model provides:
|
| 50 |
+
- **Quality Scores**: 1-100 rating for code quality
|
| 51 |
+
- **Structured Analysis**: Bugs, Performance, Security sections
|
| 52 |
+
- **Code Improvements**: Specific suggestions with examples
|
| 53 |
+
- **Professional Output**: Consistent, detailed analysis format
|
| 54 |
|
| 55 |
## 🚀 Quick Start
|
| 56 |
|
|
|
|
| 66 |
|
| 67 |
1. **Clone the repository:**
|
| 68 |
```bash
|
| 69 |
+
git clone https://github.com/arun3676/ai-code-analyzer.git
|
| 70 |
+
cd ai-code-analyzer
|
| 71 |
```
|
| 72 |
|
| 73 |
2. **Create a virtual environment:**
|
|
|
|
| 83 |
|
| 84 |
4. **Configure environment variables:**
|
| 85 |
|
| 86 |
+
Create a `.env` file in the root directory:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
```env
|
| 88 |
# API Keys - Replace with your actual API keys
|
| 89 |
OPENAI_API_KEY=your_openai_api_key_here
|
| 90 |
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
| 91 |
DEEPSEEK_API_KEY=your_deepseek_api_key_here
|
| 92 |
+
GITHUB_TOKEN=your_github_token_here # Optional, for higher API limits
|
| 93 |
```
|
| 94 |
|
| 95 |
5. **Run the application:**
|
| 96 |
```bash
|
| 97 |
+
python -m streamlit run matrix_final.py --server.port 8501
|
| 98 |
```
|
| 99 |
|
| 100 |
The application will be available at `http://localhost:8501`
|
| 101 |
|
| 102 |
## 📋 Usage
|
| 103 |
|
| 104 |
+
### Code Analysis
|
| 105 |
+
1. **Upload a file** or **paste your code** in the main panel
|
| 106 |
+
2. **Select a model** from the dropdown (OpenAI, Anthropic, or DeepSeek)
|
| 107 |
+
3. **Choose analysis type**: Code Analysis or Multimodal Analysis
|
| 108 |
+
4. **Click "Analyze Code"** to get comprehensive insights
|
| 109 |
+
|
| 110 |
+
### File Upload
|
| 111 |
+
- **Drag & drop** code files directly onto the upload area
|
| 112 |
+
- **Supported formats**: .py, .js, .java, .cpp, .c, .cs, .go, .rs, .php, .rb, .swift, .kt, .txt
|
| 113 |
+
- **File size limit**: 200MB per file
|
| 114 |
+
|
| 115 |
+
### Analysis Results
|
| 116 |
+
- **Quality Score**: 0-100 rating with color-coded indicators
|
| 117 |
+
- **Summary**: Clear description of code functionality
|
| 118 |
+
- **Issues & Bugs**: Potential problems identified
|
| 119 |
+
- **Improvements**: Actionable suggestions for better code
|
| 120 |
+
- **Security**: Security vulnerabilities and concerns
|
| 121 |
+
- **Performance**: Optimization recommendations
|
| 122 |
|
| 123 |
## 🏗️ Project Structure
|
| 124 |
|
| 125 |
```
|
| 126 |
+
ai-code-analyzer/
|
| 127 |
+
├── matrix_final.py # Main Streamlit application (deployed version)
|
| 128 |
+
├── analyzer/ # Core analysis engine
|
| 129 |
+
│ ├── __init__.py # Package initialization
|
| 130 |
+
│ ├── code_analyzer.py # Main analysis engine
|
| 131 |
+
│ ├── llm_clients.py # LLM API client implementations
|
| 132 |
+
│ ├── prompts.py # Analysis prompt templates
|
| 133 |
+
│ └── utils.py # Utility functions
|
| 134 |
├── requirements.txt # Python dependencies
|
| 135 |
+
├── render.yaml # Render deployment configuration
|
| 136 |
+
├── Procfile # Alternative deployment configuration
|
| 137 |
+
├── runtime.txt # Python version specification
|
| 138 |
+
├── README.md # This file
|
| 139 |
+
└── .env # Environment variables (create this)
|
|
|
|
|
|
|
|
|
|
| 140 |
```
|
| 141 |
|
| 142 |
## 🔧 Configuration
|
|
|
|
| 151 |
|
| 152 |
### Supported Programming Languages
|
| 153 |
|
| 154 |
+
- Python, JavaScript, Java, C++, C#, Go, Rust, PHP, Ruby, Swift, Kotlin
|
| 155 |
+
- **Auto-detection** available for most languages
|
| 156 |
+
- **Manual selection** option for specific analysis
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
|
| 158 |
## 🚀 Deployment
|
| 159 |
|
| 160 |
+
### Deploy to Render (Recommended)
|
| 161 |
|
| 162 |
+
The project is configured for **one-click deployment** on Render:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
|
| 164 |
+
1. **Fork this repository** to your GitHub account
|
| 165 |
+
2. **Connect to Render**: Go to [Render Dashboard](https://dashboard.render.com)
|
| 166 |
+
3. **Create New Web Service**: Select "Build and deploy from a Git repository"
|
| 167 |
+
4. **Connect Repository**: Link your forked repository
|
| 168 |
+
5. **Configure Environment Variables** in Render dashboard:
|
| 169 |
+
- `OPENAI_API_KEY`
|
| 170 |
+
- `ANTHROPIC_API_KEY`
|
| 171 |
+
- `DEEPSEEK_API_KEY`
|
| 172 |
+
- `GITHUB_TOKEN` (optional)
|
| 173 |
+
6. **Deploy**: Render automatically detects `render.yaml` and deploys
|
| 174 |
|
| 175 |
+
### Manual Deployment
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
|
| 177 |
+
If deploying manually, use these settings:
|
| 178 |
+
- **Build Command**: `pip install -r requirements.txt`
|
| 179 |
+
- **Start Command**: `streamlit run matrix_final.py --server.port=$PORT --server.address=0.0.0.0 --server.headless=true --server.enableCORS=false`
|
| 180 |
|
| 181 |
+
## 📊 Analysis Output
|
|
|
|
|
|
|
| 182 |
|
| 183 |
+
The tool provides structured analysis including:
|
| 184 |
|
| 185 |
+
- **🎯 Quality Score**: 0-100 rating with visual indicators
|
| 186 |
+
- **📋 Summary**: Clear description of code functionality
|
| 187 |
+
- **🐛 Issues**: Potential bugs and logical errors
|
| 188 |
+
- **💡 Improvements**: Specific actionable suggestions
|
| 189 |
+
- **🛡️ Security**: Security vulnerabilities and concerns
|
| 190 |
+
- **⚡ Performance**: Optimization opportunities
|
| 191 |
+
- **📈 Metrics**: Analysis time, model used, code statistics
|
| 192 |
|
| 193 |
+
## 🎨 UI Features
|
|
|
|
|
|
|
|
|
|
| 194 |
|
| 195 |
+
- **Matrix Theme**: Dark background with neon green accents
|
| 196 |
+
- **Responsive Design**: Works on desktop, tablet, and mobile
|
| 197 |
+
- **File Upload**: Drag & drop interface with progress indicators
|
| 198 |
+
- **Real-time Analysis**: Live progress updates during analysis
|
| 199 |
+
- **Professional Layout**: Clean, organized interface
|
| 200 |
+
- **Custom Fonts**: Share Tech Mono and Orbitron for cyberpunk feel
|
| 201 |
|
| 202 |
+
## 🧪 Development
|
| 203 |
|
| 204 |
+
### Running Locally
|
| 205 |
+
```bash
|
| 206 |
+
# Start the development server
|
| 207 |
+
python -m streamlit run matrix_final.py --server.port 8501
|
| 208 |
|
| 209 |
+
# With auto-reload for development
|
| 210 |
+
python -m streamlit run matrix_final.py --server.port 8501 --server.runOnSave true
|
| 211 |
+
```
|
| 212 |
+
|
| 213 |
+
### Code Structure
|
| 214 |
+
- **`matrix_final.py`**: Main Streamlit application with UI and routing
|
| 215 |
+
- **`analyzer/`**: Core analysis engine and LLM integrations
|
| 216 |
+
- **Custom CSS**: Embedded in the main app for Matrix theme
|
| 217 |
+
- **Error Handling**: Comprehensive error handling and user feedback
|
| 218 |
|
| 219 |
## 🤝 Contributing
|
| 220 |
|
|
|
|
| 230 |
|
| 231 |
## 🙏 Acknowledgments
|
| 232 |
|
| 233 |
+
* **Streamlit** for the amazing framework
|
| 234 |
+
* **OpenAI** for GPT models
|
| 235 |
+
* **Anthropic** for Claude
|
| 236 |
+
* **DeepSeek** for DeepSeek Coder
|
| 237 |
+
* **Render** for seamless deployment
|
| 238 |
+
* **Google Fonts** for Share Tech Mono and Orbitron fonts
|
| 239 |
|
| 240 |
## 📞 Support
|
| 241 |
|
| 242 |
If you encounter any issues or have questions:
|
| 243 |
|
| 244 |
+
1. Check the [Issues](https://github.com/arun3676/ai-code-analyzer/issues) page
|
| 245 |
2. Create a new issue with detailed information
|
| 246 |
3. Contact the maintainers
|
| 247 |
|
| 248 |
+
## 🔗 Links
|
| 249 |
+
|
| 250 |
+
- **Live Demo**: [ai-code-analyzer-tcl8.onrender.com](https://ai-code-analyzer-tcl8.onrender.com)
|
| 251 |
+
- **Repository**: [github.com/arun3676/ai-code-analyzer](https://github.com/arun3676/ai-code-analyzer)
|
| 252 |
+
- **Render Dashboard**: [dashboard.render.com](https://dashboard.render.com)
|
| 253 |
+
|
| 254 |
---
|
| 255 |
|
| 256 |
+
**Built with ❤️ by [Arun](https://github.com/arun3676)**
|
additional_samples.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Additional training samples for code analysis dataset.
|
| 4 |
+
This script generates 25 new high-quality samples to expand the dataset from 35 to 60.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import json
|
| 8 |
+
|
| 9 |
+
def create_additional_samples():
|
| 10 |
+
"""Create 25 new training samples covering diverse Python issues."""
|
| 11 |
+
|
| 12 |
+
new_samples = [
|
| 13 |
+
{
|
| 14 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import subprocess\nimport sys\n\ndef run_command(user_input):\n cmd = f\"ls -la {user_input}\"\n result = subprocess.run(cmd, shell=True, capture_output=True, text=True)\n return result.stdout\n\nif __name__ == \"__main__\":\n user_path = input(\"Enter path: \")\n print(run_command(user_path))``` [/INST] Quality Score: 15/100\n\nCRITICAL SECURITY VULNERABILITIES:\n- Command injection vulnerability via shell=True and unsanitized input\n- User can execute arbitrary commands using ; or && operators\n- No input validation or sanitization\n\nBUGS:\n- No error handling for subprocess failures\n- Will crash if command fails\n\nPERFORMANCE ISSUES:\n- Spawns shell process unnecessarily\n- No timeout protection\n\nIMPROVEMENTS:\n1. Avoid shell=True and use proper argument lists\n2. Validate and sanitize input\n3. Add proper error handling and timeouts\n\nExample improved code:\n```python\nimport subprocess\nimport os\nfrom pathlib import Path\n\ndef run_command(user_input):\n # Validate and sanitize input\n try:\n safe_path = Path(user_input).expanduser().resolve()\n if not safe_path.exists():\n raise ValueError(\"Path does not exist\")\n except Exception as e:\n raise ValueError(f\"Invalid path: {e}\")\n \n # Use proper argument list without shell\n result = subprocess.run(\n [\"ls\", \"-la\", str(safe_path)],\n capture_output=True,\n text=True,\n timeout=10\n )\n \n if result.returncode != 0:\n raise RuntimeError(f\"Command failed: {result.stderr}\")\n \n return result.stdout\n```</s>"
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import json\nfrom flask import Flask, request\n\napp = Flask(__name__)\n\n@app.route(\"/api/data\", methods=[\"POST\"])\ndef process_data():\n data = request.get_json()\n \n # Process the data\n result = {\n \"status\": \"success\",\n \"data\": data,\n \"length\": len(str(data))\n }\n \n return json.dumps(result)\n\nif __name__ == \"__main__\":\n app.run(host=\"0.0.0.0\", port=5000)``` [/INST] Quality Score: 42/100\n\nBUGS:\n- No error handling for malformed JSON requests\n- Missing Content-Type validation\n- No input size limits\n\nPERFORMANCE ISSUES:\n- Converting data to string just for length calculation is inefficient\n- No request timeout handling\n\nSECURITY CONCERNS:\n- Binding to 0.0.0.0 exposes service to all interfaces\n- No authentication or rate limiting\n- Potential DoS via large payloads\n- No input validation\n\nIMPROVEMENTS:\n1. Add proper error handling and validation\n2. Implement security measures\n3. Optimize performance\n\nExample improved code:\n```python\nimport json\nfrom flask import Flask, request, jsonify\nfrom functools import wraps\n\napp = Flask(__name__)\n\nMAX_PAYLOAD_SIZE = 1024 * 1024 # 1MB limit\n\ndef validate_json(f):\n @wraps(f)\n def decorated_function(*args, **kwargs):\n if not request.is_json:\n return jsonify({\"error\": \"Content-Type must be application/json\"}), 400\n \n content_length = request.content_length\n if content_length and content_length > MAX_PAYLOAD_SIZE:\n return jsonify({\"error\": \"Payload too large\"}), 413\n \n try:\n request.json # Validate JSON parsing\n except Exception:\n return jsonify({\"error\": \"Invalid JSON\"}), 400\n \n return f(*args, **kwargs)\n return decorated_function\n\n@app.route(\"/api/data\", methods=[\"POST\"])\n@validate_json\ndef process_data():\n data = request.get_json()\n \n # Validate required fields\n if not isinstance(data, dict):\n return jsonify({\"error\": \"Data must be a JSON object\"}), 400\n \n result = {\n \"status\": \"success\",\n \"data\": data,\n \"field_count\": len(data)\n }\n \n return jsonify(result)\n\nif __name__ == \"__main__\":\n app.run(host=\"127.0.0.1\", port=5000, debug=False)\n```</s>"
|
| 18 |
+
},
|
| 19 |
+
{
|
| 20 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import threading\nimport time\n\nclass Counter:\n def __init__(self):\n self.value = 0\n \n def increment(self):\n temp = self.value\n time.sleep(0.001) # Simulate work\n self.value = temp + 1\n \n def get_value(self):\n return self.value\n\ncounter = Counter()\n\ndef worker():\n for _ in range(1000):\n counter.increment()\n\n# Create multiple threads\nthreads = []\nfor i in range(5):\n t = threading.Thread(target=worker)\n threads.append(t)\n t.start()\n\n# Wait for all threads to complete\nfor t in threads:\n t.join()\n\nprint(f\"Final count: {counter.get_value()}\")``` [/INST] Quality Score: 38/100\n\nBUGS:\n- Race condition in increment() method\n- Non-atomic read-modify-write operation\n- Final count will be less than expected (5000)\n\nPERFORMANCE ISSUES:\n- Unnecessary sleep in critical section\n- No thread synchronization\n\nSECURITY CONCERNS:\n- Race condition could lead to data corruption\n- No protection against concurrent access\n\nIMPROVEMENTS:\n1. Use proper synchronization mechanisms\n2. Make operations atomic\n\nExample improved code:\n```python\nimport threading\n\nclass Counter:\n def __init__(self):\n self._value = 0\n self._lock = threading.Lock()\n \n def increment(self):\n with self._lock:\n # Simulate work outside critical section\n time.sleep(0.001)\n self._value += 1\n \n def get_value(self):\n with self._lock:\n return self._value\n\n# Alternative: Use atomic operations\nimport threading\n\nclass AtomicCounter:\n def __init__(self):\n self._value = 0\n self._lock = threading.RLock()\n \n def increment(self):\n with self._lock:\n self._value += 1\n \n def get_value(self):\n with self._lock:\n return self._value\n```</s>"
|
| 21 |
+
},
|
| 22 |
+
{
|
| 23 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import os\nimport tempfile\n\ndef process_file(file_content):\n # Create temporary file\n temp_file = tempfile.NamedTemporaryFile(delete=False)\n temp_file.write(file_content.encode())\n temp_file.close()\n \n # Process the file\n with open(temp_file.name, \"r\") as f:\n content = f.read()\n \n # Clean up\n os.remove(temp_file.name)\n \n return content.upper()\n\nif __name__ == \"__main__\":\n result = process_file(\"Hello, World!\")\n print(result)``` [/INST] Quality Score: 55/100\n\nBUGS:\n- No error handling if file operations fail\n- Potential file descriptor leak if exception occurs after file creation\n- No cleanup if processing fails\n\nPERFORMANCE ISSUES:\n- Unnecessary file I/O for simple string operations\n- Creates temporary file for small data\n\nSECURITY CONCERNS:\n- Temporary file might not be cleaned up if process crashes\n- No validation of file_content size\n\nIMPROVEMENTS:\n1. Use context managers for proper cleanup\n2. Avoid unnecessary file operations\n3. Add proper error handling\n\nExample improved code:\n```python\nimport tempfile\nimport os\nfrom contextlib import contextmanager\n\n@contextmanager\ndef temporary_file(content):\n \"\"\"Context manager for temporary file with automatic cleanup.\"\"\"\n temp_file = None\n try:\n with tempfile.NamedTemporaryFile(mode=\"w+\", delete=False, encoding=\"utf-8\") as tf:\n tf.write(content)\n temp_file = tf.name\n yield temp_file\n finally:\n if temp_file and os.path.exists(temp_file):\n try:\n os.unlink(temp_file)\n except OSError:\n pass # File already deleted\n\ndef process_file(file_content):\n # Validate input\n if not isinstance(file_content, str):\n raise ValueError(\"File content must be a string\")\n \n # For simple operations, avoid file I/O\n if len(file_content) < 1024: # Small content\n return file_content.upper()\n \n # For larger content, use temporary file\n with temporary_file(file_content) as temp_path:\n with open(temp_path, \"r\", encoding=\"utf-8\") as f:\n content = f.read()\n return content.upper()\n```</s>"
|
| 24 |
+
},
|
| 25 |
+
{
|
| 26 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import hashlib\nimport os\n\ndef hash_file(filename):\n \"\"\"Calculate MD5 hash of a file.\"\"\"\n hash_md5 = hashlib.md5()\n with open(filename, \"rb\") as f:\n for chunk in iter(lambda: f.read(4096), b\"\"):\n hash_md5.update(chunk)\n return hash_md5.hexdigest()\n\ndef verify_integrity(file_path, expected_hash):\n \"\"\"Verify file integrity against expected hash.\"\"\"\n actual_hash = hash_file(file_path)\n return actual_hash == expected_hash\n\nif __name__ == \"__main__\":\n file_path = input(\"Enter file path: \")\n hash_value = hash_file(file_path)\n print(f\"MD5: {hash_value}\")\n \n expected = input(\"Enter expected hash: \")\n if verify_integrity(file_path, expected):\n print(\"File integrity verified!\")\n else:\n print(\"File integrity check failed!\")``` [/INST] Quality Score: 65/100\n\nBUGS:\n- No error handling for file operations\n- No validation of input parameters\n- Will crash if file doesn't exist or can't be read\n\nPERFORMANCE ISSUES:\n- MD5 is fast but not cryptographically secure\n- No file size limits\n\nSECURITY CONCERNS:\n- MD5 is vulnerable to collision attacks\n- No protection against path traversal\n- No input sanitization\n\nIMPROVEMENTS:\n1. Use cryptographically secure hash function\n2. Add proper error handling and validation\n3. Secure file path handling\n\nExample improved code:\n```python\nimport hashlib\nimport os\nfrom pathlib import Path\n\ndef hash_file(file_path, algorithm=\"sha256\"):\n \"\"\"Calculate hash of a file using specified algorithm.\"\"\"\n file_path = Path(file_path).resolve()\n \n if not file_path.exists():\n raise FileNotFoundError(f\"File not found: {file_path}\")\n \n if not file_path.is_file():\n raise ValueError(f\"Path is not a file: {file_path}\")\n \n # Choose hash algorithm\n if algorithm.lower() == \"md5\":\n hasher = hashlib.md5()\n elif algorithm.lower() == \"sha256\":\n hasher = hashlib.sha256()\n elif algorithm.lower() == \"sha1\":\n hasher = hashlib.sha1()\n else:\n raise ValueError(f\"Unsupported algorithm: {algorithm}\")\n \n try:\n with open(file_path, \"rb\") as f:\n while chunk := f.read(8192): # 8KB chunks\n hasher.update(chunk)\n return hasher.hexdigest()\n except IOError as e:\n raise IOError(f\"Error reading file: {e}\")\n\ndef verify_integrity(file_path, expected_hash, algorithm=\"sha256\"):\n \"\"\"Verify file integrity against expected hash.\"\"\"\n try:\n actual_hash = hash_file(file_path, algorithm)\n return actual_hash.lower() == expected_hash.lower()\n except Exception as e:\n print(f\"Verification failed: {e}\")\n return False\n```</s>"
|
| 27 |
+
}
|
| 28 |
+
]
|
| 29 |
+
|
| 30 |
+
# Continue with more samples to reach 25 total...
|
| 31 |
+
more_samples = [
|
| 32 |
+
{
|
| 33 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import socket\nimport threading\n\nclass SimpleServer:\n def __init__(self, host=\"localhost\", port=8080):\n self.host = host\n self.port = port\n self.clients = []\n \n def handle_client(self, client_socket):\n while True:\n data = client_socket.recv(1024)\n if not data:\n break\n response = f\"Echo: {data.decode()}\"\n client_socket.send(response.encode())\n client_socket.close()\n \n def start(self):\n server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n server.bind((self.host, self.port))\n server.listen(5)\n \n while True:\n client, addr = server.accept()\n self.clients.append(client)\n thread = threading.Thread(target=self.handle_client, args=(client,))\n thread.start()\n\nif __name__ == \"__main__\":\n server = SimpleServer()\n server.start()``` [/INST] Quality Score: 33/100\n\nBUGS:\n- No error handling for socket operations\n- Threads are never joined or cleaned up\n- No graceful shutdown mechanism\n- No connection limits or timeouts\n\nPERFORMANCE ISSUES:\n- Creates unlimited threads (potential thread exhaustion)\n- No connection pooling or limits\n- Memory leak with growing clients list\n\nSECURITY CONCERNS:\n- No authentication or authorization\n- No input validation or sanitization\n- Vulnerable to DoS attacks\n- No rate limiting\n\nIMPROVEMENTS:\n1. Add proper error handling and resource management\n2. Implement connection limits and timeouts\n3. Add security measures\n\nExample improved code:\n```python\nimport socket\nimport threading\nimport time\nfrom concurrent.futures import ThreadPoolExecutor\n\nclass SimpleServer:\n def __init__(self, host=\"127.0.0.1\", port=8080, max_connections=10):\n self.host = host\n self.port = port\n self.max_connections = max_connections\n self.running = False\n self.executor = ThreadPoolExecutor(max_workers=max_connections)\n \n def handle_client(self, client_socket, addr):\n \"\"\"Handle client connection with proper error handling.\"\"\"\n try:\n client_socket.settimeout(30) # 30 second timeout\n \n while self.running:\n try:\n data = client_socket.recv(1024)\n if not data:\n break\n \n # Basic input validation\n message = data.decode(\"utf-8\", errors=\"ignore\")\n if len(message) > 1000: # Limit message size\n response = \"Error: Message too long\"\n else:\n response = f\"Echo: {message}\"\n \n client_socket.send(response.encode(\"utf-8\"))\n except socket.timeout:\n break\n except Exception as e:\n print(f\"Error handling client {addr}: {e}\")\n finally:\n try:\n client_socket.close()\n except:\n pass\n \n def start(self):\n \"\"\"Start the server with proper resource management.\"\"\"\n self.running = True\n \n try:\n server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n server.bind((self.host, self.port))\n server.listen(self.max_connections)\n \n print(f\"Server listening on {self.host}:{self.port}\")\n \n while self.running:\n try:\n client, addr = server.accept()\n self.executor.submit(self.handle_client, client, addr)\n except Exception as e:\n if self.running:\n print(f\"Error accepting connection: {e}\")\n except Exception as e:\n print(f\"Server error: {e}\")\n finally:\n server.close()\n \n def stop(self):\n \"\"\"Gracefully stop the server.\"\"\"\n self.running = False\n self.executor.shutdown(wait=True)\n```</s>"
|
| 34 |
+
},
|
| 35 |
+
{
|
| 36 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import re\n\ndef validate_email(email):\n \"\"\"Validate email address using regex.\"\"\"\n pattern = r\"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\"\n return bool(re.match(pattern, email))\n\ndef extract_emails(text):\n \"\"\"Extract all email addresses from text.\"\"\"\n pattern = r\"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\"\n return re.findall(pattern, text)\n\ndef sanitize_input(user_input):\n \"\"\"Sanitize user input by removing special characters.\"\"\"\n return re.sub(r\"[^a-zA-Z0-9@._-]\", \"\", user_input)\n\nif __name__ == \"__main__\":\n email = input(\"Enter email: \")\n if validate_email(email):\n print(\"Valid email!\")\n else:\n print(\"Invalid email!\")\n \n text = input(\"Enter text to extract emails: \")\n emails = extract_emails(text)\n print(f\"Found emails: {emails}\")\n \n user_input = input(\"Enter text to sanitize: \")\n clean = sanitize_input(user_input)\n print(f\"Sanitized: {clean}\")``` [/INST] Quality Score: 72/100\n\nBUGS:\n- Email regex is too permissive and may allow invalid emails\n- No handling of edge cases (empty strings, None values)\n- Sanitization function is too aggressive and may break valid input\n\nPERFORMANCE ISSUES:\n- Regex compilation happens on every call (should be compiled once)\n- No input size limits\n\nSECURITY CONCERNS:\n- Email validation regex can be bypassed\n- Sanitization may not be sufficient for all use cases\n- No protection against regex DoS attacks\n\nIMPROVEMENTS:\n1. Use proper email validation library\n2. Pre-compile regex patterns\n3. Add proper input validation\n\nExample improved code:\n```python\nimport re\nfrom email_validator import validate_email, EmailNotValidError\n\nclass EmailValidator:\n def __init__(self):\n # Pre-compile regex patterns for better performance\n self.email_pattern = re.compile(\n r\"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\",\n re.IGNORECASE\n )\n self.extract_pattern = re.compile(\n r\"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}\",\n re.IGNORECASE\n )\n \n def validate_email(self, email):\n \"\"\"Validate email address using proper validation.\"\"\"\n if not email or not isinstance(email, str):\n return False\n \n if len(email) > 254: # RFC 5321 limit\n return False\n \n try:\n # Use proper email validation\n validate_email(email)\n return True\n except EmailNotValidError:\n return False\n \n def extract_emails(self, text):\n \"\"\"Extract all email addresses from text.\"\"\"\n if not text or not isinstance(text, str):\n return []\n \n if len(text) > 10000: # Limit input size\n raise ValueError(\"Input text too long\")\n \n matches = self.extract_pattern.findall(text)\n return [email for email in matches if self.validate_email(email)]\n \n def sanitize_input(self, user_input, max_length=1000):\n \"\"\"Sanitize user input with proper validation.\"\"\"\n if not user_input or not isinstance(user_input, str):\n return \"\"\n \n if len(user_input) > max_length:\n user_input = user_input[:max_length]\n \n # Remove potentially dangerous characters but preserve email structure\n sanitized = re.sub(r\"[<>\"'&]\", \"\", user_input)\n return sanitized\n\n# Usage\nvalidator = EmailValidator()\n```</s>"
|
| 37 |
+
}
|
| 38 |
+
]
|
| 39 |
+
|
| 40 |
+
# Add 18 more samples to reach 25 total
|
| 41 |
+
additional_samples = [
|
| 42 |
+
{
|
| 43 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import os\nimport shutil\n\ndef backup_file(source, destination):\n \"\"\"Backup a file to destination.\"\"\"\n if os.path.exists(source):\n shutil.copy2(source, destination)\n print(f\"Backed up {source} to {destination}\")\n else:\n print(f\"Source file {source} does not exist\")\n\nif __name__ == \"__main__\":\n source = input(\"Enter source file: \")\n dest = input(\"Enter destination: \")\n backup_file(source, dest)``` [/INST] Quality Score: 48/100\n\nBUGS:\n- No error handling for file operations\n- No validation of input paths\n- Will crash if destination directory doesn't exist\n\nPERFORMANCE ISSUES:\n- No file size limits\n- No progress indication for large files\n\nSECURITY CONCERNS:\n- Path traversal vulnerability in user input\n- No validation of file paths\n- Could overwrite system files\n\nIMPROVEMENTS:\n1. Add proper error handling and path validation\n2. Implement security measures\n3. Add progress indication\n\nExample improved code:\n```python\nimport os\nimport shutil\nfrom pathlib import Path\n\ndef backup_file(source, destination):\n \"\"\"Safely backup a file to destination.\"\"\"\n try:\n source_path = Path(source).resolve()\n dest_path = Path(destination).resolve()\n \n # Validate source\n if not source_path.exists():\n raise FileNotFoundError(f\"Source file not found: {source_path}\")\n \n if not source_path.is_file():\n raise ValueError(f\"Source is not a file: {source_path}\")\n \n # Validate destination\n dest_dir = dest_path.parent\n if not dest_dir.exists():\n dest_dir.mkdir(parents=True, exist_ok=True)\n \n # Check if destination already exists\n if dest_path.exists():\n response = input(f\"Destination exists. Overwrite? (y/n): \")\n if response.lower() != 'y':\n print(\"Backup cancelled\")\n return False\n \n # Perform backup\n shutil.copy2(source_path, dest_path)\n print(f\"Successfully backed up {source_path} to {dest_path}\")\n return True\n \n except Exception as e:\n print(f\"Backup failed: {e}\")\n return False\n```</s>"
|
| 44 |
+
},
|
| 45 |
+
{
|
| 46 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import urllib.request\nimport json\n\ndef fetch_data(url):\n \"\"\"Fetch data from URL and return JSON.\"\"\"\n response = urllib.request.urlopen(url)\n data = response.read()\n return json.loads(data.decode())\n\ndef process_api_data(url):\n \"\"\"Process data from API endpoint.\"\"\"\n data = fetch_data(url)\n results = []\n for item in data:\n if 'name' in item and 'value' in item:\n results.append({\n 'name': item['name'],\n 'value': item['value'] * 2\n })\n return results\n\nif __name__ == \"__main__\":\n api_url = input(\"Enter API URL: \")\n results = process_api_data(api_url)\n print(f\"Processed {len(results)} items\")\n for result in results:\n print(f\"{result['name']}: {result['value']}\")``` [/INST] Quality Score: 52/100\n\nBUGS:\n- No error handling for network requests\n- No validation of URL format\n- Assumes data structure without validation\n\nPERFORMANCE ISSUES:\n- No timeout for network requests\n- No caching mechanism\n- Loads entire response into memory\n\nSECURITY CONCERNS:\n- No URL validation (potential SSRF)\n- No SSL certificate verification\n- No rate limiting\n\nIMPROVEMENTS:\n1. Add proper error handling and validation\n2. Implement security measures\n3. Add timeout and caching\n\nExample improved code:\n```python\nimport urllib.request\nimport urllib.parse\nimport json\nimport ssl\nfrom urllib.error import URLError, HTTPError\n\nclass APIClient:\n def __init__(self, timeout=30):\n self.timeout = timeout\n self.ctx = ssl.create_default_context()\n \n def fetch_data(self, url):\n \"\"\"Safely fetch data from URL.\"\"\"\n # Validate URL\n parsed = urllib.parse.urlparse(url)\n if not parsed.scheme or not parsed.netloc:\n raise ValueError(\"Invalid URL format\")\n \n # Only allow HTTP/HTTPS\n if parsed.scheme not in ['http', 'https']:\n raise ValueError(\"Only HTTP/HTTPS URLs are allowed\")\n \n try:\n request = urllib.request.Request(url)\n request.add_header('User-Agent', 'Python-API-Client/1.0')\n \n with urllib.request.urlopen(request, timeout=self.timeout, context=self.ctx) as response:\n if response.status != 200:\n raise HTTPError(url, response.status, \"HTTP Error\", response.headers, None)\n \n data = response.read()\n if len(data) > 10 * 1024 * 1024: # 10MB limit\n raise ValueError(\"Response too large\")\n \n return json.loads(data.decode('utf-8'))\n \n except URLError as e:\n raise ConnectionError(f\"Network error: {e}\")\n except json.JSONDecodeError as e:\n raise ValueError(f\"Invalid JSON response: {e}\")\n \n def process_api_data(self, url):\n \"\"\"Process data from API with validation.\"\"\"\n try:\n data = self.fetch_data(url)\n \n if not isinstance(data, list):\n raise ValueError(\"Expected list data\")\n \n results = []\n for item in data:\n if not isinstance(item, dict):\n continue\n \n if 'name' in item and 'value' in item:\n try:\n value = float(item['value'])\n results.append({\n 'name': str(item['name']),\n 'value': value * 2\n })\n except (ValueError, TypeError):\n continue\n \n return results\n \n except Exception as e:\n print(f\"Error processing API data: {e}\")\n return []\n```</s>"
|
| 47 |
+
},
|
| 48 |
+
{
|
| 49 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import logging\nimport os\n\ndef setup_logging():\n logging.basicConfig(\n level=logging.INFO,\n format='%(asctime)s - %(levelname)s - %(message)s',\n filename='app.log'\n )\n\ndef log_user_action(user_id, action, details):\n \"\"\"Log user actions for audit trail.\"\"\"\n message = f\"User {user_id} performed {action}: {details}\"\n logging.info(message)\n\ndef log_error(error_msg, user_id=None):\n \"\"\"Log error messages.\"\"\"\n if user_id:\n logging.error(f\"User {user_id} encountered error: {error_msg}\")\n else:\n logging.error(f\"System error: {error_msg}\")\n\nif __name__ == \"__main__\":\n setup_logging()\n log_user_action(\"user123\", \"login\", \"successful login\")\n log_error(\"Database connection failed\")``` [/INST] Quality Score: 68/100\n\nBUGS:\n- No error handling for file operations\n- No log rotation or size limits\n- No validation of input parameters\n\nPERFORMANCE ISSUES:\n- No async logging\n- File I/O blocks on every log\n- No log compression\n\nSECURITY CONCERNS:\n- Logs may contain sensitive information\n- No log sanitization\n- Potential log injection attacks\n\nIMPROVEMENTS:\n1. Add proper error handling and log rotation\n2. Implement log sanitization\n3. Add security measures\n\nExample improved code:\n```python\nimport logging\nimport logging.handlers\nimport os\nimport re\nfrom datetime import datetime\n\nclass SecureLogger:\n def __init__(self, log_file='app.log', max_size=10*1024*1024, backup_count=5):\n self.logger = logging.getLogger('secure_app')\n self.logger.setLevel(logging.INFO)\n \n # Clear existing handlers\n self.logger.handlers.clear()\n \n # Create rotating file handler\n handler = logging.handlers.RotatingFileHandler(\n log_file, maxBytes=max_size, backupCount=backup_count\n )\n \n # Create formatter\n formatter = logging.Formatter(\n '%(asctime)s - %(levelname)s - %(message)s',\n datefmt='%Y-%m-%d %H:%M:%S'\n )\n handler.setFormatter(formatter)\n \n self.logger.addHandler(handler)\n \n # Prevent sensitive data patterns\n self.sensitive_patterns = [\n r'password[=:]\\s*\\S+',\n r'token[=:]\\s*\\S+',\n r'key[=:]\\s*\\S+',\n r'\\b\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b' # Credit card\n ]\n \n def sanitize_message(self, message):\n \"\"\"Remove sensitive information from log messages.\"\"\"\n for pattern in self.sensitive_patterns:\n message = re.sub(pattern, '[REDACTED]', message, flags=re.IGNORECASE)\n return message\n \n def log_user_action(self, user_id, action, details):\n \"\"\"Log user actions with sanitization.\"\"\"\n if not user_id or not action:\n return\n \n message = f\"User {user_id} performed {action}: {details}\"\n sanitized_message = self.sanitize_message(message)\n self.logger.info(sanitized_message)\n \n def log_error(self, error_msg, user_id=None):\n \"\"\"Log error messages with sanitization.\"\"\"\n if not error_msg:\n return\n \n if user_id:\n message = f\"User {user_id} encountered error: {error_msg}\"\n else:\n message = f\"System error: {error_msg}\"\n \n sanitized_message = self.sanitize_message(message)\n self.logger.error(sanitized_message)\n\n# Usage\nlogger = SecureLogger()\n```</s>"
|
| 50 |
+
}
|
| 51 |
+
]
|
| 52 |
+
|
| 53 |
+
# Add remaining samples to reach 25 total
|
| 54 |
+
final_samples = [
|
| 55 |
+
{
|
| 56 |
+
"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import random\nimport string\n\ndef generate_password(length=8):\n \"\"\"Generate a random password.\"\"\"\n chars = string.ascii_letters + string.digits\n password = ''.join(random.choice(chars) for _ in range(length))\n return password\n\ndef create_user(username, email):\n \"\"\"Create a new user account.\"\"\"\n password = generate_password()\n user_data = {\n 'username': username,\n 'email': email,\n 'password': password\n }\n # In real app, save to database\n print(f\"User created: {username} with password: {password}\")\n return user_data\n\nif __name__ == \"__main__\":\n username = input(\"Enter username: \")\n email = input(\"Enter email: \")\n user = create_user(username, email)``` [/INST] Quality Score: 25/100\n\nCRITICAL SECURITY VULNERABILITIES:\n- Weak password generation (no special characters, predictable)\n- Password printed to console (major security risk)\n- No password strength validation\n- No input validation\n\nBUGS:\n- No error handling\n- No validation of username/email format\n\nPERFORMANCE ISSUES:\n- Uses random.choice in loop (slow for long passwords)\n\nSECURITY CONCERNS:\n- Passwords logged to console\n- Weak entropy\n- No password policy enforcement\n\nIMPROVEMENTS:\n1. Use cryptographically secure random generation\n2. Implement proper password policies\n3. Never log passwords\n\nExample improved code:\n```python\nimport secrets\nimport string\nimport re\nfrom typing import Optional\n\nclass PasswordGenerator:\n def __init__(self):\n self.lowercase = string.ascii_lowercase\n self.uppercase = string.ascii_uppercase\n self.digits = string.digits\n self.special = \"!@#$%^&*\"\n self.all_chars = self.lowercase + self.uppercase + self.digits + self.special\n \n def generate_password(self, length=12, min_special=1, min_upper=1, min_lower=1, min_digits=1):\n \"\"\"Generate cryptographically secure password.\"\"\"\n if length < 8:\n raise ValueError(\"Password must be at least 8 characters\")\n \n password = []\n \n # Ensure minimum requirements\n password.extend(secrets.choice(self.special) for _ in range(min_special))\n password.extend(secrets.choice(self.uppercase) for _ in range(min_upper))\n password.extend(secrets.choice(self.lowercase) for _ in range(min_lower))\n password.extend(secrets.choice(self.digits) for _ in range(min_digits))\n \n # Fill remaining length\n remaining = length - len(password)\n password.extend(secrets.choice(self.all_chars) for _ in range(remaining))\n \n # Shuffle to randomize positions\n secrets.SystemRandom().shuffle(password)\n \n return ''.join(password)\n \n def validate_password(self, password):\n \"\"\"Validate password strength.\"\"\"\n if len(password) < 8:\n return False, \"Password must be at least 8 characters\"\n \n if not re.search(r'[a-z]', password):\n return False, \"Password must contain lowercase letters\"\n \n if not re.search(r'[A-Z]', password):\n return False, \"Password must contain uppercase letters\"\n \n if not re.search(r'\\d', password):\n return False, \"Password must contain digits\"\n \n if not re.search(r'[!@#$%^&*]', password):\n return False, \"Password must contain special characters\"\n \n return True, \"Password is strong\"\n\ndef create_user(username, email):\n \"\"\"Create user with secure password.\"\"\"\n # Validate inputs\n if not username or not email:\n raise ValueError(\"Username and email required\")\n \n if len(username) < 3:\n raise ValueError(\"Username must be at least 3 characters\")\n \n # Generate secure password\n generator = PasswordGenerator()\n password = generator.generate_password()\n \n user_data = {\n 'username': username,\n 'email': email,\n 'password': password # In real app, hash this immediately\n }\n \n # NEVER log passwords!\n print(f\"User created: {username}\")\n return user_data\n```</s>"
|
| 57 |
+
}
|
| 58 |
+
]
|
| 59 |
+
|
| 60 |
+
# Add all samples together to reach 25 total
|
| 61 |
+
all_samples = new_samples + more_samples + additional_samples + final_samples
|
| 62 |
+
|
| 63 |
+
return all_samples
|
| 64 |
+
|
| 65 |
+
if __name__ == "__main__":
|
| 66 |
+
samples = create_additional_samples()
|
| 67 |
+
print(f"Created {len(samples)} additional training samples")
|
| 68 |
+
|
| 69 |
+
# Save to file
|
| 70 |
+
with open("additional_samples.json", "w") as f:
|
| 71 |
+
json.dump(samples, f, indent=2)
|
| 72 |
+
|
| 73 |
+
print("Samples saved to additional_samples.json")
|
analyst_dataset.jsonl
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```def calculate_fibonacci(n):\n if n <= 0:\n return 0\n elif n == 1:\n return 1\n else:\n return calculate_fibonacci(n-1) + calculate_fibonacci(n-2)\n\n# Test the function\nfor i in range(10):\n result = calculate_fibonacci(i)\n print(f\"Fibonacci({i}) = {result}\")``` [/INST] Quality Score: 65/100\n\nBUGS:\n- Recursive implementation without memoization causes exponential time complexity\n- Will cause stack overflow for large values of n\n- No input validation for negative numbers beyond the first check\n\nPERFORMANCE ISSUES:\n- Time complexity: O(2^n) - extremely inefficient\n- Space complexity: O(n) due to recursion stack\n- Repeated calculations for same values\n\nSECURITY CONCERNS:\n- No protection against extremely large inputs that could cause DoS\n- No input sanitization\n\nIMPROVEMENTS:\n1. Use memoization or iterative approach for O(n) time complexity\n2. Add input validation with proper error handling\n3. Add maximum input limit to prevent abuse\n4. Consider using dynamic programming approach\n\nExample improved code:\n```python\ndef calculate_fibonacci(n):\n if n < 0:\n raise ValueError(\"Input must be non-negative\")\n if n > 1000: # Prevent abuse\n raise ValueError(\"Input too large\")\n \n if n <= 1:\n return n\n \n a, b = 0, 1\n for _ in range(2, n + 1):\n a, b = b, a + b\n return b\n```</s>"}
|
| 2 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import os\n\ndef read_user_file(filename):\n file_path = os.path.join(\"/home/user/\", filename)\n with open(file_path, \"r\") as f:\n content = f.read()\n return content\n\n# Usage\nuser_input = input(\"Enter filename: \")\ndata = read_user_file(user_input)\nprint(data)``` [/INST] Quality Score: 25/100\n\nCRITICAL SECURITY VULNERABILITIES:\n- Path traversal vulnerability: User can access any file by using \"../\" in filename\n- No input validation or sanitization\n- Hardcoded directory path creates inflexibility\n- No error handling for file operations\n\nBUGS:\n- Will crash if file doesn't exist\n- Will crash if user doesn't have read permissions\n- No handling for binary files (will try to decode as text)\n\nPERFORMANCE ISSUES:\n- Loads entire file into memory (problematic for large files)\n- No file size limits\n\nIMPROVEMENTS:\n1. Validate and sanitize input filename\n2. Use absolute path validation\n3. Add proper error handling\n4. Implement file size limits\n5. Use pathlib for safer path handling\n\nExample improved code:\n```python\nimport os\nfrom pathlib import Path\n\ndef read_user_file(filename):\n # Validate filename\n if not filename or \"..\" in filename or \"/\" in filename:\n raise ValueError(\"Invalid filename\")\n \n # Create safe path\n base_dir = Path(\"/home/user/\")\n file_path = base_dir / filename\n \n # Ensure path is within allowed directory\n if not file_path.resolve().is_relative_to(base_dir.resolve()):\n raise ValueError(\"Access denied\")\n \n # Check file size\n if file_path.stat().st_size > 10 * 1024 * 1024: # 10MB limit\n raise ValueError(\"File too large\")\n \n try:\n with open(file_path, \"r\") as f:\n return f.read()\n except FileNotFoundError:\n raise FileNotFoundError(\"File not found\")\n except PermissionError:\n raise PermissionError(\"Access denied\")\n```</s>"}
|
| 3 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```class UserManager:\n def __init__(self):\n self.users = {}\n \n def add_user(self, username, password):\n self.users[username] = password\n \n def authenticate(self, username, password):\n if username in self.users:\n if self.users[username] == password:\n return True\n return False\n \n def get_user_info(self, username):\n return self.users.get(username, None)\n\n# Usage\nmanager = UserManager()\nmanager.add_user(\"admin\", \"password123\")\nprint(manager.authenticate(\"admin\", \"password123\"))``` [/INST] Quality Score: 30/100\n\nCRITICAL SECURITY VULNERABILITIES:\n- Passwords stored in plain text (major security risk)\n- No password hashing or encryption\n- No password strength validation\n- No protection against brute force attacks\n- No session management\n\nBUGS:\n- No input validation for username/password\n- No handling of edge cases (empty strings, None values)\n- No duplicate user prevention\n\nPERFORMANCE ISSUES:\n- In-memory storage (data lost on restart)\n- No database persistence\n- No indexing for large user bases\n\nIMPROVEMENTS:\n1. Hash passwords using bcrypt or similar\n2. Add input validation and sanitization\n3. Implement proper session management\n4. Use database for persistence\n5. Add password strength requirements\n6. Implement rate limiting for authentication attempts\n\nExample improved code:\n```python\nimport hashlib\nimport secrets\nfrom typing import Optional\n\nclass UserManager:\n def __init__(self):\n self.users = {}\n self.sessions = {}\n \n def _hash_password(self, password: str) -> str:\n salt = secrets.token_hex(16)\n password_hash = hashlib.pbkdf2_hmac('sha256', \n password.encode('utf-8'), \n salt.encode('utf-8'), \n 100000)\n return f\"{salt}:{password_hash.hex()}\"\n \n def _verify_password(self, password: str, stored_hash: str) -> bool:\n salt, hash_value = stored_hash.split(':')\n password_hash = hashlib.pbkdf2_hmac('sha256',\n password.encode('utf-8'),\n salt.encode('utf-8'),\n 100000)\n return password_hash.hex() == hash_value\n \n def add_user(self, username: str, password: str) -> bool:\n if not username or not password:\n raise ValueError(\"Username and password required\")\n if len(password) < 8:\n raise ValueError(\"Password must be at least 8 characters\")\n if username in self.users:\n raise ValueError(\"User already exists\")\n \n self.users[username] = self._hash_password(password)\n return True\n \n def authenticate(self, username: str, password: str) -> bool:\n if username not in self.users:\n return False\n return self._verify_password(password, self.users[username])\n```</s>"}
|
| 4 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import re, pathlib, requests\nfrom urllib.parse import urlparse\nfrom html.parser import HTMLParser\n\nclass TitleParser(HTMLParser):\n def __init__(self): super().__init__(); self.in_title=False; self.title=[]\n def handle_starttag(self, tag, attrs): self.in_title = tag.lower()==\"title\"\n def handle_endtag(self, tag): \n if tag.lower()==\"title\": self.in_title=False\n def handle_data(self, data): \n if self.in_title: self.title.append(data)\n\nALLOWED_SCHEMES = {\"http\",\"https\"}\nBLOCKED_HOSTS = {\"169.254.169.254\",\"localhost\",\"127.0.0.1\",\"::1\"}\n\ndef safe_fetch(url: str):\n u = urlparse(url)\n if u.scheme not in ALLOWED_SCHEMES or u.hostname in BLOCKED_HOSTS:\n raise ValueError(\"URL not allowed\")\n with requests.get(url, timeout=10, stream=True) as r:\n r.raise_for_status()\n text = r.text # consider iter_content for huge pages\n p = TitleParser(); p.feed(text)\n title = \"\".join(p.title).strip() or \"No Title\"\n safe_name = re.sub(r\"[^a-zA-Z0-9_.-]\", \"_\", u.hostname or \"page\")\n pathlib.Path(f\"{safe_name}.html\").write_text(text, encoding=\"utf-8\")\n return title``` [/INST] Quality Score: 48/100\n\nBUGS:\n- No error handling for network failures or malformed HTML\n- File overwrites without checking if it already exists\n- No validation of URL format before parsing\n\nPERFORMANCE ISSUES:\n- Loads entire response into memory with r.text instead of streaming\n- No caching mechanism for repeated requests to same URL\n\nSECURITY CONCERNS:\n- File writes to current directory without path validation\n- No size limits on downloaded content (potential DoS)\n- No validation of HTML content before parsing\n\nIMPROVEMENTS:\n1. Add proper error handling and file size limits\n```python\nimport re, pathlib, requests\nfrom urllib.parse import urlparse\nfrom html.parser import HTMLParser\n\ndef safe_fetch(url: str, max_size: int = 10 * 1024 * 1024):\n u = urlparse(url)\n if u.scheme not in ALLOWED_SCHEMES or u.hostname in BLOCKED_HOSTS:\n raise ValueError(\"URL not allowed\")\n \n try:\n with requests.get(url, timeout=10, stream=True) as r:\n r.raise_for_status()\n content_length = int(r.headers.get('content-length', 0))\n if content_length > max_size:\n raise ValueError(\"Content too large\")\n \n content = b\"\"\n for chunk in r.iter_content(chunk_size=8192):\n content += chunk\n if len(content) > max_size:\n raise ValueError(\"Content too large\")\n \n text = content.decode('utf-8', errors='ignore')\n except requests.RequestException as e:\n raise ValueError(f\"Network error: {e}\")\n \n # Parse and save with proper error handling\n p = TitleParser()\n try:\n p.feed(text)\n except Exception:\n pass # Continue even if HTML parsing fails\n \n title = \"\".join(p.title).strip() or \"No Title\"\n safe_name = re.sub(r\"[^a-zA-Z0-9_.-]\", \"_\", u.hostname or \"page\")\n \n # Create safe output directory\n output_dir = pathlib.Path(\"downloads\")\n output_dir.mkdir(exist_ok=True)\n output_path = output_dir / f\"{safe_name}.html\"\n \n output_path.write_text(text, encoding=\"utf-8\")\n return title\n```</s>"}
|
| 5 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import sqlite3\n\ndef get_user(email):\n conn = sqlite3.connect(\"app.db\")\n cur = conn.cursor()\n # vulnerable string interpolation\n q = f\"SELECT id, email, role FROM users WHERE email = '{email}'\"\n rows = cur.execute(q).fetchall()\n conn.close()\n return rows[0] if rows else None\n\ndef delete_user(email):\n # missing commit and no existence check\n conn = sqlite3.connect(\"app.db\")\n cur = conn.cursor()\n cur.execute(f\"DELETE FROM users WHERE email = '{email}'\")\n conn.close()\n\nif __name__ == \"__main__\":\n e = input(\"Email: \")\n print(get_user(e))\n if input(\"Delete? (y/n): \") == \"y\":\n delete_user(e)``` [/INST] Quality Score: 32/100\n\nBUGS:\n- delete_user never commits; deletion may not persist\n- get_user returns None for empty table but code assumes tuple downstream in callers (potential TypeError)\n\nPERFORMANCE ISSUES:\n- Opens/closes a new connection per call; consider pooling or reuse for batch operations\n\nSECURITY CONCERNS:\n- SQL injection via string interpolation for email\n- Potential information disclosure by printing raw tuple\n\nIMPROVEMENTS:\n1. Use parameterized queries and ensure transactions are committed\n```python\nimport sqlite3\n\ndef with_conn(db=\"app.db\"):\n conn = sqlite3.connect(db)\n try:\n yield conn\n conn.commit()\n finally:\n conn.close()\n\ndef get_user(email):\n with sqlite3.connect(\"app.db\") as conn:\n cur = conn.execute(\"SELECT id, email, role FROM users WHERE email = ?\", (email,))\n return cur.fetchone()\n\ndef delete_user(email):\n with sqlite3.connect(\"app.db\") as conn:\n conn.execute(\"DELETE FROM users WHERE email = ?\", (email,))\n```</s>"}
|
| 6 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```from flask import Flask, request, jsonify\n\napp = Flask(__name__)\nAPI_TOKEN = \"secret\" # hardcoded\n\n@app.route(\"/admin/users\", methods=[\"GET\"])\ndef list_users():\n # auth via query param; vulnerable\n if request.args.get(\"token\") != API_TOKEN:\n return jsonify({\"error\": \"unauthorized\"}), 401\n # pretend to read from file\n with open(\"users.json\") as f:\n return f.read() # returns raw string, wrong content-type\n\n@app.route(\"/echo\", methods=[\"POST\"])\ndef echo():\n # reflects untrusted data directly\n msg = request.json.get(\"msg\", \"\")\n return f\"<div>{msg}</div>\"\n\nif __name__ == \"__main__\":\n app.run(debug=True)``` [/INST] Quality Score: 35/100\n\nBUGS:\n- /admin/users returns plain string without JSON content-type; clients may fail parsing\n- Missing error handling if users.json not found\n\nPERFORMANCE ISSUES:\n- Reading file on every request instead of caching\n\nSECURITY CONCERNS:\n- Hardcoded secret; weak auth via token in query string (leaks via logs)\n- XSS in /echo by reflecting unsanitized HTML\n- debug=True exposes Werkzeug debugger with arbitrary code execution in some configs\n\nIMPROVEMENTS:\n1. Use header-based auth, environment secrets, safe JSON responses, and HTML escaping\n```python\nimport os, html, json\nfrom flask import Flask, request, jsonify, Response\n\napp = Flask(__name__)\nAPI_TOKEN = os.environ.get(\"API_TOKEN\")\n\ndef require_token():\n token = request.headers.get(\"Authorization\",\"\").replace(\"Bearer \",\"\")\n if not API_TOKEN or token != API_TOKEN:\n return jsonify({\"error\":\"unauthorized\"}), 401\n\n@app.get(\"/admin/users\")\ndef list_users():\n auth = require_token()\n if auth: return auth\n try:\n with open(\"users.json\",\"r\",encoding=\"utf-8\") as f:\n data = json.load(f)\n return jsonify(data)\n except FileNotFoundError:\n return jsonify({\"error\":\"not found\"}), 404\n\n@app.post(\"/echo\")\ndef echo():\n msg = request.json.get(\"msg\",\"\")\n return Response(f\"<div>{html.escape(msg)}</div>\", mimetype=\"text/html\")\n```</s>"}
|
| 7 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import os, time\n\nTMP_DIR = \"/tmp\"\n\ndef process_upload(filename, content):\n # race: check then use predictable path\n path = os.path.join(TMP_DIR, filename)\n if not os.path.exists(path):\n open(path, \"w\").write(content)\n # later read it\n time.sleep(0.5) # simulate delay\n data = open(path).read()\n return data.upper()\n\nif __name__ == \"__main__\":\n print(process_upload(input(\"name: \"), \"hello\"))``` [/INST] Quality Score: 44/100\n\nBUGS:\n- No file closing (implicit close but errors may leak descriptors)\n- No input validation on filename; may include path separators\n\nPERFORMANCE ISSUES:\n- Sleep delays processing; unnecessary blocking\n- Reads whole file even if large\n\nSECURITY CONCERNS:\n- TOCTOU race: attacker can symlink path to sensitive file after existence check\n- Path traversal via filename allowing writes to arbitrary locations\n\nIMPROVEMENTS:\n1. Use secure temporary files and sanitize paths; open with exclusive flags\n```python\nimport io, os, tempfile\n\ndef process_upload(content: str):\n with tempfile.NamedTemporaryFile(mode=\"w+\", delete=False, dir=tempfile.gettempdir(), encoding=\"utf-8\") as tf:\n tf.write(content)\n tf.flush()\n tf.seek(0)\n data = tf.read()\n return data.upper()\n```</s>"}
|
| 8 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import csv\n\ndef load_prices(path):\n rows = []\n with open(path) as f:\n for r in csv.DictReader(f):\n # trusting numeric fields; may be blank\n price = float(r[\"price\"]) # ValueError possible\n # evaluating discount expression directly from CSV (dangerous)\n discount = eval(r.get(\"discount\",\"0\")) # arbitrary code exec\n rows.append({\"name\": r[\"name\"], \"final\": price - discount})\n return rows\n\nif __name__ == \"__main__\":\n print(load_prices(\"prices.csv\"))``` [/INST] Quality Score: 27/100\n\nBUGS:\n- Unhandled ValueError for missing or non-numeric price\n- discount application can produce negative final prices with no checks\n\nPERFORMANCE ISSUES:\n- No streaming/validation—okay for small files, but no batching for large inputs\n\nSECURITY CONCERNS:\n- eval on CSV field allows arbitrary code execution\n- No path validation; could read unexpected files\n\nIMPROVEMENTS:\n1. Replace eval with safe parsing and validate numbers\n```python\nimport csv\nfrom decimal import Decimal, InvalidOperation\n\ndef parse_decimal(s):\n try: return Decimal(s)\n except (InvalidOperation, TypeError): return None\n\ndef load_prices(path):\n out=[]\n with open(path, newline=\"\", encoding=\"utf-8\") as f:\n for r in csv.DictReader(f):\n price = parse_decimal(r.get(\"price\"))\n disc = parse_decimal(r.get(\"discount\") or \"0\")\n if price is None or disc is None: continue\n final = max(Decimal(\"0\"), price - disc)\n out.append({\"name\": r.get(\"name\",\"\"), \"final\": str(final)})\n return out\n```</s>"}
|
| 9 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import asyncio\n\nasync def fetch(i):\n await asyncio.sleep(0.1)\n return i*i\n\nasync def main():\n tasks = []\n for i in range(20):\n tasks.append(fetch(i)) # forgot to create tasks with ensure_future\n results = []\n for t in tasks:\n # not awaited; result is coroutine object\n results.append(t)\n print(results)\n\nif __name__ == \"__main__\":\n loop = asyncio.get_event_loop()\n loop.run_until_complete(main())\n # bad: nested run in same loop (would crash if called again)\n asyncio.run(main())``` [/INST] Quality Score: 26/100\n\nBUGS:\n- Appends coroutine objects, never awaited, leading to no execution\n- Double-running event loop with loop.run_until_complete and then asyncio.run may raise RuntimeError\n\nPERFORMANCE ISSUES:\n- Serial awaits inside a loop would be slow even if fixed; should gather\n\nSECURITY CONCERNS:\n- None specific beyond stability\n\nIMPROVEMENTS:\n1. Use asyncio.gather and avoid double loop management\n```python\nimport asyncio\n\nasync def fetch(i):\n await asyncio.sleep(0.1)\n return i*i\n\nasync def main():\n results = await asyncio.gather(*(fetch(i) for i in range(20)))\n print(results)\n\nif __name__ == \"__main__\":\n asyncio.run(main())\n```</s>"}
|
| 10 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```cache = []\n\ndef read_big_file(path):\n # loads entire file and caches forever -> memory growth\n with open(path, \"rb\") as f:\n data = f.read()\n cache.append(data)\n return len(data)\n\ndef process_many(paths):\n total = 0\n for p in paths:\n total += read_big_file(p)\n return total``` [/INST] Quality Score: 41/100\n\nBUGS:\n- No bounds on cache; memory leak across calls\n- No file existence/error handling\n\nPERFORMANCE ISSUES:\n- Reads entire files into memory; should stream for large files\n- Appending binary blobs prevents GC and increases fragmentation\n\nSECURITY CONCERNS:\n- If paths are user-controlled, could load sensitive files\n\nIMPROVEMENTS:\n1. Stream and limit cache by size or use LRU\n```python\nfrom functools import lru_cache\nimport os\n\n@lru_cache(maxsize=128)\ndef file_size(path):\n return os.path.getsize(path)\n\ndef process_many(paths):\n return sum(file_size(p) for p in paths if os.path.exists(p))\n```</s>"}
|
| 11 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```def transfer(a, b, amount):\n try:\n a['balance'] -= amount\n if a['balance'] < 0:\n raise ValueError(\"insufficient\")\n b['balance'] += amount\n except:\n # swallow all errors\n pass\n\nif __name__ == \"__main__\":\n alice = {\"balance\": 100}\n bob = {\"balance\": 50}\n transfer(alice, bob, 200)\n print(alice, bob)``` [/INST] Quality Score: 38/100\n\nBUGS:\n- Bare except swallows insufficient funds error, leaving inconsistent state (Alice reduced but Bob not credited if error after)\n- No return value indicating success/failure\n\nPERFORMANCE ISSUES:\n- None significant\n\nSECURITY CONCERNS:\n- Silent failures complicate auditing and could hide fraud\n\nIMPROVEMENTS:\n1. Use explicit exception handling and atomicity\n```python\ndef transfer(a, b, amount):\n if amount <= 0:\n raise ValueError(\"amount must be positive\")\n if a[\"balance\"] < amount:\n raise ValueError(\"insufficient funds\")\n a[\"balance\"] -= amount\n b[\"balance\"] += amount\n return True\n```</s>"}
|
| 12 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import os\n\nDEBUG = True\nSECRET_KEY = \"supersecret\"\nDB_URL = \"postgres://user:pass@localhost/db\"\n\ndef connect():\n # pretend to connect using DB_URL\n print(\"Connecting to\", DB_URL)\n\nif __name__ == \"__main__\":\n if DEBUG:\n print(\"Debug mode on\")\n connect()``` [/INST] Quality Score: 52/100\n\nBUGS:\n- None functional, but poor separation of config from code\n\nPERFORMANCE ISSUES:\n- Printing secrets to console in debug could end up in logs\n\nSECURITY CONCERNS:\n- Hardcoded secrets and credentials in source control\n- Debug mode enabled by default\n\nIMPROVEMENTS:\n1. Move secrets to environment variables and default to secure values\n```python\nimport os\n\nDEBUG = os.getenv(\"APP_DEBUG\",\"0\") == \"1\"\nSECRET_KEY = os.getenv(\"SECRET_KEY\")\nDB_URL = os.getenv(\"DATABASE_URL\")\n\ndef connect():\n if not DB_URL:\n raise RuntimeError(\"DATABASE_URL not set\")\n # connect using DB_URL\n```</s>"}
|
| 13 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```from flask import Flask, request, render_template_string\n\napp = Flask(__name__)\n\n@app.route(\"/greet\")\ndef greet():\n name = request.args.get(\"name\",\"world\")\n # unsafe: marking user input as safe HTML\n tpl = \"<h1>Hello, {{ name|safe }}</h1>\"\n return render_template_string(tpl, name=name)\n\nif __name__ == \"__main__\":\n app.run()``` [/INST] Quality Score: 46/100\n\nBUGS:\n- None functional, but template marks untrusted input as safe\n\nPERFORMANCE ISSUES:\n- Using render_template_string for every request rather than compiled templates\n\nSECURITY CONCERNS:\n- Reflected XSS via name parameter using |safe\n\nIMPROVEMENTS:\n1. Escape user input and use templates\n```python\nfrom flask import Flask, request, render_template_string\n\napp = Flask(__name__)\n\nTPL = \"<h1>Hello, {{ name }}</h1>\"\n\n@app.get(\"/greet\")\ndef greet():\n name = request.args.get(\"name\",\"world\")\n return render_template_string(TPL, name=name)\n```</s>"}
|
| 14 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import os\n\ndef list_dir(user_input):\n # command injection via shell=True\n cmd = f\"ls -la {user_input}\"\n os.system(cmd)\n\nif __name__ == \"__main__\":\n list_dir(input(\"Path: \"))``` [/INST] Quality Score: 28/100\n\nBUGS:\n- Fails on paths with spaces or special characters\n\nPERFORMANCE ISSUES:\n- Spawns a shell process unnecessarily\n\nSECURITY CONCERNS:\n- Command injection by passing ; rm -rf / or similar\n- No validation of path\n\nIMPROVEMENTS:\n1. Use subprocess without shell and validate input\n```python\nimport subprocess\nfrom pathlib import Path\n\ndef list_dir(path_str):\n p = Path(path_str).expanduser().resolve()\n result = subprocess.run([\"ls\",\"-la\", str(p)], check=True, capture_output=True, text=True)\n return result.stdout\n```</s>"}
|
| 15 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import os\nfrom flask import Flask, request, send_file\n\napp = Flask(__name__)\n\nBASE = \"/var/data\"\n\n@app.route(\"/download\")\ndef download():\n name = request.args.get(\"name\",\"\")\n path = os.path.join(BASE, name) # no normalization\n if os.path.exists(path):\n return send_file(path)\n return \"Not found\", 404``` [/INST] Quality Score: 43/100\n\nBUGS:\n- No method checks; only GET assumed\n\nPERFORMANCE ISSUES:\n- Repeated os.path.exists without caching is fine; main issue is security\n\nSECURITY CONCERNS:\n- Path traversal via name=../../etc/passwd to escape BASE\n- Possible disclosure of any readable file\n\nIMPROVEMENTS:\n1. Normalize and ensure path stays within BASE\n```python\nfrom pathlib import Path\nfrom flask import Flask, request, send_file, abort\n\nBASE = Path(\"/var/data\").resolve()\n\n@app.get(\"/download\")\ndef download():\n name = request.args.get(\"name\",\"\")\n target = (BASE / name).resolve()\n if not str(target).startswith(str(BASE)) or not target.exists():\n abort(404)\n return send_file(target)\n```</s>"}
|
| 16 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```from flask import Flask, request\nimport time, os\n\napp = Flask(__name__)\nUPLOAD_DIR = \"uploads\"\n\n@app.post(\"/upload\")\ndef upload():\n f = request.files[\"file\"]\n path = os.path.join(UPLOAD_DIR, f.filename)\n f.save(path) # save immediately\n # scan after saving (race: window where file is accessible)\n time.sleep(0.2) # simulate scan\n if f.filename.endswith(\".exe\"):\n os.remove(path) # too late; already served by static server?\n return \"Rejected\", 400\n return \"OK\" ``` [/INST] Quality Score: 49/100\n\nBUGS:\n- No check if UPLOAD_DIR exists; may crash\n\nPERFORMANCE ISSUES:\n- Sleep-based scan blocks worker thread\n\nSECURITY CONCERNS:\n- Race condition: file saved and potentially accessible before validation\n- Trusts filename; content-type and magic bytes not checked\n\nIMPROVEMENTS:\n1. Validate first to a quarantine path and atomically move after scanning\n```python\nfrom pathlib import Path\nimport tempfile, shutil\n\nUPLOAD_DIR = Path(\"uploads\"); UPLOAD_DIR.mkdir(exist_ok=True)\n\ndef is_safe(stream):\n head = stream.read(512); stream.seek(0)\n return b\"MZ\" not in head # toy check\n\n@app.post(\"/upload\")\ndef upload():\n f = request.files[\"file\"]\n with tempfile.NamedTemporaryFile(delete=False, dir=UPLOAD_DIR) as tmp:\n f.save(tmp.name)\n with open(tmp.name,\"rb\") as s:\n if not is_safe(s):\n os.remove(tmp.name); return \"Rejected\", 400\n final = UPLOAD_DIR / f.filename\n shutil.move(tmp.name, final)\n return \"OK\"\n```</s>"}
|
| 17 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import logging\n\nlogging.basicConfig(level=logging.INFO)\n\ndef login(username, password):\n # logs sensitive info\n logging.info(\"Login attempt user=%s password=%s\", username, password)\n if username == \"admin\" and password == \"admin\":\n return True\n return False``` [/INST] Quality Score: 50/100\n\nBUGS:\n- Hardcoded credentials\n\nPERFORMANCE ISSUES:\n- None significant\n\nSECURITY CONCERNS:\n- Logs plaintext passwords\n- Trivial credentials\n\nIMPROVEMENTS:\n1. Remove sensitive logging and use proper auth\n```python\nimport logging\n\ndef login(username, password):\n logging.info(\"Login attempt for user=%s\", username)\n # verify against hashed password store (omitted)\n return False\n```</s>"}
|
| 18 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import hashlib, os\n\ndef hash_password(password, salt=b\"fixedsalt\"):\n # weak MD5 and constant salt\n return hashlib.md5(salt + password.encode()).hexdigest()\n\ndef verify(password, digest):\n return hash_password(password) == digest\n\nif __name__ == \"__main__\":\n d = hash_password(\"secret\")\n print(verify(\"secret\", d))``` [/INST] Quality Score: 34/100\n\nBUGS:\n- None functional, but cryptographically unsafe\n\nPERFORMANCE ISSUES:\n- MD5 is fast, making brute force cheap\n\nSECURITY CONCERNS:\n- MD5 is broken for password hashing\n- Fixed salt allows rainbow table reuse\n\nIMPROVEMENTS:\n1. Use a dedicated password KDF like bcrypt/argon2 with per-user salt\n```python\nfrom argon2 import PasswordHasher\nph = PasswordHasher()\n\ndef hash_password(pw): return ph.hash(pw)\ndef verify(pw, digest): \n try: ph.verify(digest, pw); return True\n except Exception: return False\n```</s>"}
|
| 19 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import jwt\n\nSECRET = \"topsecret\"\n\ndef parse_token(token):\n # disables verification by passing options\n data = jwt.decode(token, options={\"verify_signature\": False})\n return data.get(\"user\")\n\nif __name__ == \"__main__\":\n print(parse_token(input(\"JWT: \")))``` [/INST] Quality Score: 29/100\n\nBUGS:\n- Assumes user claim exists; may raise AttributeError if not dict\n\nPERFORMANCE ISSUES:\n- None notable\n\nSECURITY CONCERNS:\n- Signature verification disabled allows forged tokens\n- No audience/issuer checks\n\nIMPROVEMENTS:\n1. Verify signature and validate claims\n```python\nimport jwt, datetime\nSECRET=\"topsecret\"\nALGO=\"HS256\"\n\ndef parse_token(token):\n data = jwt.decode(token, SECRET, algorithms=[ALGO], options={\"require\":[\"exp\",\"iat\",\"sub\"]}, audience=\"myapi\")\n return data.get(\"sub\")\n```</s>"}
|
| 20 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import threading, time\n\ncounter = 0\n\ndef worker(n):\n global counter\n for _ in range(n):\n tmp = counter\n time.sleep(0.001) # simulate work\n counter = tmp + 1\n\nthreads = [threading.Thread(target=worker, args=(1000,)) for _ in range(4)]\n[t.start() for t in threads]\n[t.join() for t in threads]\nprint(\"counter =\", counter)``` [/INST] Quality Score: 45/100\n\nBUGS:\n- Data race on counter leading to lost updates; final value < 4000\n\nPERFORMANCE ISSUES:\n- Frequent context switches due to sleep\n\nSECURITY CONCERNS:\n- None\n\nIMPROVEMENTS:\n1. Use a Lock or atomic primitives\n```python\nimport threading\n\ncounter = 0\nlock = threading.Lock()\n\ndef worker(n):\n global counter\n for _ in range(n):\n with lock:\n counter += 1\n```</s>"}
|
| 21 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import requests\n\ndef get_json(url):\n # disables SSL verification\n r = requests.get(url, verify=False) # insecure\n if r.status_code == 200:\n return r.json()\n return {}\n\nif __name__ == \"__main__\":\n print(get_json(\"https://example.com/api\"))``` [/INST] Quality Score: 53/100\n\nBUGS:\n- No exception handling for JSON decoding\n\nPERFORMANCE ISSUES:\n- No timeout or retries; may hang\n\nSECURITY CONCERNS:\n- verify=False exposes to MITM\n- No certificate pinning for sensitive APIs\n\nIMPROVEMENTS:\n1. Enable TLS verification, add timeouts and basic retry\n```python\nimport requests\n\nSESSION = requests.Session()\nADAPTER = requests.adapters.HTTPAdapter(max_retries=3)\nSESSION.mount(\"https://\", ADAPTER)\n\ndef get_json(url, timeout=5):\n r = SESSION.get(url, timeout=timeout)\n r.raise_for_status()\n return r.json()\n```</s>"}
|
| 22 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```def paginate(items, page, size):\n # off-by-one: page starts at 1 but uses 0-based math incorrectly\n start = page * size\n end = start + size - 1\n return items[start:end]\n\nif __name__ == \"__main__\":\n print(paginate(list(range(10)), 1, 3))``` [/INST] Quality Score: 58/100\n\nBUGS:\n- Off-by-one errors: page=1 should start at index 0; end slicing exclusive misused\n- Negative or zero page/size not validated\n\nPERFORMANCE ISSUES:\n- None\n\nSECURITY CONCERNS:\n- None\n\nIMPROVEMENTS:\n1. Correct indices and validate inputs\n```python\ndef paginate(items, page, size):\n if page < 1 or size < 1: return []\n start = (page - 1) * size\n end = start + size\n return items[start:end]\n```</s>"}
|
| 23 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```def most_frequent(nums):\n # O(n^2) counting\n best = None\n bestc = -1\n for x in nums:\n c = 0\n for y in nums:\n if x == y:\n c += 1\n if c > bestc:\n bestc = c\n best = x\n return best``` [/INST] Quality Score: 62/100\n\nBUGS:\n- Works but ties are arbitrary; behavior unspecified\n\nPERFORMANCE ISSUES:\n- Quadratic time; slow for large lists\n\nSECURITY CONCERNS:\n- None\n\nIMPROVEMENTS:\n1. Use a hashmap for linear time\n```python\nfrom collections import Counter\ndef most_frequent(nums):\n return Counter(nums).most_common(1)[0][0] if nums else None\n```</s>"}
|
| 24 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import asyncio\nimport websockets\n\nclients = set()\n\nasync def handler(ws):\n clients.add(ws) # never removed on disconnect if error\n async for msg in ws:\n for c in clients:\n await c.send(msg) # exceptions not handled\n # missing finally to remove ws\n\nasync def main():\n async with websockets.serve(handler, \"0.0.0.0\", 8765):\n await asyncio.Future()\n\nasyncio.run(main())``` [/INST] Quality Score: 47/100\n\nBUGS:\n- Clients not removed on errors; memory leak\n- Broadcast loop fails if one client breaks; others starve\n\nPERFORMANCE ISSUES:\n- Serial awaits per client; slow with many clients\n\nSECURITY CONCERNS:\n- No authentication or origin checks\n\nIMPROVEMENTS:\n1. Remove clients in finally and handle send errors\n```python\nasync def handler(ws):\n clients.add(ws)\n try:\n async for msg in ws:\n dead=set()\n for c in clients:\n try: await c.send(msg)\n except: dead.add(c)\n clients.difference_update(dead)\n finally:\n clients.discard(ws)\n```</s>"}
|
| 25 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```from datetime import datetime\nimport time\n\ndef log_event(ts_str):\n # parse naive datetime string and compare to now\n event = datetime.strptime(ts_str, \"%Y-%m-%d %H:%M:%S\")\n now = datetime.now()\n diff = (now - event).total_seconds()\n print(\"Seconds ago:\", diff)\n\nif __name__ == \"__main__\":\n log_event(\"2025-10-09 12:00:00\")``` [/INST] Quality Score: 60/100\n\nBUGS:\n- Treats naive datetimes as local time; mismatches if input intended as UTC\n\nPERFORMANCE ISSUES:\n- None\n\nSECURITY CONCERNS:\n- None\n\nIMPROVEMENTS:\n1. Use timezone-aware datetimes and explicit TZ\n```python\nfrom datetime import datetime, timezone\n\ndef log_event(ts_str):\n event = datetime.strptime(ts_str, \"%Y-%m-%d %H:%M:%S\").replace(tzinfo=timezone.utc)\n now = datetime.now(timezone.utc)\n print(\"Seconds ago:\", (now - event).total_seconds())\n```</s>"}
|
| 26 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```def is_equal(a, b):\n # exact float equality\n return a == b\n\nif __name__ == \"__main__\":\n print(is_equal(0.1+0.2, 0.3))``` [/INST] Quality Score: 70/100\n\nBUGS:\n- Floating point equality leads to false negatives due to precision\n\nPERFORMANCE ISSUES:\n- None\n\nSECURITY CONCERNS:\n- None\n\nIMPROVEMENTS:\n1. Use tolerance-based comparison\n```python\nimport math\ndef is_equal(a, b, eps=1e-9):\n return math.isclose(a, b, rel_tol=1e-9, abs_tol=eps)\n```</s>"}
|
| 27 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```def add_item(item, items=[]):\n # default mutable arg: shared list across calls\n items.append(item)\n return items\n\nif __name__ == \"__main__\":\n print(add_item(1))\n print(add_item(2))``` [/INST] Quality Score: 63/100\n\nBUGS:\n- Default list persists across invocations, causing unintended accumulation\n\nPERFORMANCE ISSUES:\n- None\n\nSECURITY CONCERNS:\n- None\n\nIMPROVEMENTS:\n1. Default to None and create per-call list\n```python\ndef add_item(item, items=None):\n if items is None: items = []\n items.append(item)\n return items\n```</s>"}
|
| 28 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import pickle\nfrom flask import Flask, request\n\napp = Flask(__name__)\n\n@app.post(\"/load\")\ndef load():\n data = request.data # untrusted\n obj = pickle.loads(data) # RCE risk\n return {\"type\": str(type(obj))}\n\nif __name__ == \"__main__\":\n app.run()``` [/INST] Quality Score: 22/100\n\nBUGS:\n- No error handling for malformed payloads\n\nPERFORMANCE ISSUES:\n- Could block on large payloads; no size limits\n\nSECURITY CONCERNS:\n- Insecure deserialization: pickle.loads on untrusted data enables arbitrary code execution\n\nIMPROVEMENTS:\n1. Use safe serialization (JSON) and cap payload size\n```python\nfrom flask import Flask, request, jsonify\n\n@app.post(\"/load\")\ndef load():\n if request.content_length and request.content_length > 1_000_000:\n return jsonify({\"error\":\"payload too large\"}), 413\n try:\n obj = request.get_json(force=True)\n return jsonify({\"keys\": list(obj.keys()) if isinstance(obj, dict) else None})\n except Exception:\n return jsonify({\"error\":\"invalid json\"}), 400\n```</s>"}
|
| 29 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import json, time\nfrom http.server import BaseHTTPRequestHandler, HTTPServer\n\nclass H(BaseHTTPRequestHandler):\n sessions = {} # in-memory sessions; never expire\n\n def do_POST(self):\n if self.path == \"/login\":\n ln = int(self.headers.get(\"Content-Length\", \"0\"))\n body = self.rfile.read(ln).decode()\n data = json.loads(body)\n if data.get(\"user\") and data.get(\"pass\"):\n token = data[\"user\"] + str(time.time())\n H.sessions[token] = data[\"user\"]\n self.send_response(200); self.end_headers()\n self.wfile.write(token.encode())\n else:\n self.send_response(400); self.end_headers()\n\nserver = HTTPServer((\"0.0.0.0\", 8080), H)\nserver.serve_forever()``` [/INST] Quality Score: 40/100\n\nBUGS:\n- No content-type checks; JSON errors unhandled\n- Reusing class variable sessions without thread safety (server may be multithreaded depending on mixin)\n\nPERFORMANCE ISSUES:\n- Sessions grow unbounded; memory leak\n\nSECURITY CONCERNS:\n- Session token is predictable (username + timestamp)\n- No HTTPS enforcement, no SameSite/HttpOnly cookies, tokens sent in body/plain\n- No password verification\n\nIMPROVEMENTS:\n1. Use secure random tokens with expiry and proper error handling\n```python\nimport os, json, secrets, time\nfrom http.server import BaseHTTPRequestHandler, HTTPServer\n\nclass H(BaseHTTPRequestHandler):\n sessions = {}\n def do_POST(self):\n try:\n data = json.loads(self.rfile.read(int(self.headers.get(\"Content-Length\",\"0\"))))\n except Exception:\n self.send_response(400); self.end_headers(); return\n if self.path == \"/login\":\n if not data.get(\"user\") or not data.get(\"pass\"):\n self.send_response(400); self.end_headers(); return\n token = secrets.token_urlsafe(32)\n H.sessions[token] = {\"u\": data[\"user\"], \"exp\": time.time()+3600}\n self.send_response(200); self.end_headers(); self.wfile.write(token.encode())\n```</s>"}
|
| 30 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import re\n\ndef parse_email(s):\n # overly permissive regex; accepts invalid and allows catastrophic backtracking\n pattern = r\"(.+)+@(.+)+\\.(.+)+\"\n return bool(re.match(pattern, s))\n\nif __name__ == \"__main__\":\n print(parse_email(\"a\"*10000 + \"@x.com\"))``` [/INST] Quality Score: 56/100\n\nBUGS:\n- Regex can exhibit catastrophic backtracking on long strings, causing CPU spikes\n- Accepts many invalid emails; false positives\n\nPERFORMANCE ISSUES:\n- Regex complexity leads to potential DoS\n\nSECURITY CONCERNS:\n- Potential ReDoS if user-controlled input is validated using this pattern\n\nIMPROVEMENTS:\n1. Use anchored, simpler regex or email.utils\n```python\nimport re\nEMAIL_RE = re.compile(r\"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\")\ndef parse_email(s): return bool(EMAIL_RE.match(s))\n```</s>"}
|
| 31 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import json, time\nimport requests\n\ndef poll_job(api_url, job_id):\n # tight loop without backoff; no timeout\n while True:\n r = requests.get(f\"{api_url}/jobs/{job_id}\")\n if r.status_code == 200 and r.json().get(\"status\") == \"done\":\n return r.json()\n time.sleep(0.1)\n\nif __name__ == \"__main__\":\n print(poll_job(\"https://example.com/api\", \"123\"))``` [/INST] Quality Score: 57/100\n\nBUGS:\n- No exit on error or unknown statuses; potential infinite loop\n\nPERFORMANCE ISSUES:\n- Aggressive polling (100 ms) can hammer the API\n- No timeout or retry policy\n\nSECURITY CONCERNS:\n- No TLS verification customization; default OK but missing auth headers\n\nIMPROVEMENTS:\n1. Add timeouts, backoff, and max wait\n```python\nimport time, requests\n\ndef poll_job(api_url, job_id, timeout=30):\n end = time.time()+timeout\n delay = 0.5\n while time.time() < end:\n r = requests.get(f\"{api_url}/jobs/{job_id}\", timeout=5)\n r.raise_for_status()\n st = r.json().get(\"status\")\n if st == \"done\": return r.json()\n if st in {\"failed\",\"canceled\"}: raise RuntimeError(st)\n time.sleep(delay); delay = min(5.0, delay*1.5)\n raise TimeoutError(\"job not done\")\n```</s>"}
|
| 32 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import json\nfrom flask import Flask, request\n\napp = Flask(__name__)\n\n@app.post(\"/api/items\")\ndef items():\n data = request.json # may be None\n # expects 'qty' int but trusts client\n total = data[\"price\"] * data[\"qty\"] # TypeError if string\n return {\"total\": total}\n\nif __name__ == \"__main__\":\n app.run()``` [/INST] Quality Score: 59/100\n\nBUGS:\n- Assumes JSON body exists; KeyError/TypeError on missing/invalid fields\n- No type casting; arithmetic on strings raises errors\n\nPERFORMANCE ISSUES:\n- None significant\n\nSECURITY CONCERNS:\n- Trusting client-calculated fields could lead to abuse in real apps\n\nIMPROVEMENTS:\n1. Validate and coerce input with defaults\n```python\nfrom flask import Flask, request, jsonify\n\n@app.post(\"/api/items\")\ndef items():\n data = request.get_json(silent=True) or {}\n try:\n price = float(data.get(\"price\", 0))\n qty = int(data.get(\"qty\", 0))\n except ValueError:\n return jsonify({\"error\":\"invalid types\"}), 400\n return jsonify({\"total\": price * qty})\n```</s>"}
|
| 33 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import threading, json\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\n\ndb = {\"hits\": 0, \"items\": []}\n\nclass H(BaseHTTPRequestHandler):\n def do_POST(self):\n ln = int(self.headers.get(\"Content-Length\",\"0\"))\n body = self.rfile.read(ln)\n item = json.loads(body).get(\"item\")\n # race: no lock protecting db\n db[\"items\"].append(item)\n db[\"hits\"] += 1\n self.send_response(201); self.end_headers()\n\nsrv = HTTPServer((\"0.0.0.0\", 8000), H)\nsrv.serve_forever()``` [/INST] Quality Score: 46/100\n\nBUGS:\n- No error handling for invalid JSON/body\n- Global mutable dict accessed from multiple threads without synchronization (HTTPServer can be threaded in variations)\n\nPERFORMANCE ISSUES:\n- In-memory store grows unbounded\n\nSECURITY CONCERNS:\n- No authentication and accepts arbitrary data\n\nIMPROVEMENTS:\n1. Add locks and validation, or use a thread-safe queue/datastore\n```python\nimport threading\nlock = threading.Lock()\ndef add_item(item):\n with lock:\n db[\"items\"].append(item)\n db[\"hits\"] += 1\n```</s>"}
|
| 34 |
+
{"text": "<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```import yaml\n\ndef load_conf(path):\n with open(path) as f:\n return yaml.load(f, Loader=yaml.Loader) # unsafe loader\n\nif __name__ == \"__main__\":\n print(load_conf(\"config.yml\"))``` [/INST] Quality Score: 55/100\n\nBUGS:\n- Crashes on missing file; no handling\n\nPERFORMANCE ISSUES:\n- None\n\nSECURITY CONCERNS:\n- Unsafe YAML loader can construct arbitrary objects (code execution vectors)\n\nIMPROVEMENTS:\n1. Use safe_load and validate schema\n```python\nimport yaml, jsonschema\n\ndef load_conf(path):\n with open(path, encoding=\"utf-8\") as f:\n data = yaml.safe_load(f)\n # validate with schema (omitted)\n return data\n```</s>"}
|
analyst_dataset_expanded.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
app.py
DELETED
|
@@ -1,340 +0,0 @@
|
|
| 1 |
-
import streamlit as st
|
| 2 |
-
import os
|
| 3 |
-
import time
|
| 4 |
-
from dotenv import load_dotenv
|
| 5 |
-
from analyzer import CodeAnalyzer
|
| 6 |
-
import json
|
| 7 |
-
|
| 8 |
-
# Load environment variables - only in development
|
| 9 |
-
if os.path.exists('.env'):
|
| 10 |
-
load_dotenv()
|
| 11 |
-
|
| 12 |
-
# Simple health check for Render
|
| 13 |
-
def is_health_check():
|
| 14 |
-
"""Check if this is a health check request"""
|
| 15 |
-
try:
|
| 16 |
-
# Check URL parameters
|
| 17 |
-
if "health" in st.query_params or "healthz" in st.query_params:
|
| 18 |
-
return True
|
| 19 |
-
return False
|
| 20 |
-
except:
|
| 21 |
-
return False
|
| 22 |
-
|
| 23 |
-
# Handle health check
|
| 24 |
-
if is_health_check():
|
| 25 |
-
st.json({
|
| 26 |
-
"status": "healthy",
|
| 27 |
-
"service": "ai-code-analyzer",
|
| 28 |
-
"timestamp": time.time(),
|
| 29 |
-
"uptime": "ok"
|
| 30 |
-
})
|
| 31 |
-
st.stop()
|
| 32 |
-
|
| 33 |
-
# Page config
|
| 34 |
-
st.set_page_config(
|
| 35 |
-
page_title="LLM Code Analyzer",
|
| 36 |
-
page_icon="🔍",
|
| 37 |
-
layout="wide",
|
| 38 |
-
initial_sidebar_state="expanded"
|
| 39 |
-
)
|
| 40 |
-
|
| 41 |
-
# Custom CSS for professional look
|
| 42 |
-
st.markdown("""
|
| 43 |
-
<style>
|
| 44 |
-
.main { padding-top: 2rem; }
|
| 45 |
-
.stButton > button {
|
| 46 |
-
width: 100%;
|
| 47 |
-
background-color: #0e1117;
|
| 48 |
-
border: 1px solid #262730;
|
| 49 |
-
font-weight: 500;
|
| 50 |
-
}
|
| 51 |
-
.stButton > button:hover {
|
| 52 |
-
border-color: #4a4b5e;
|
| 53 |
-
}
|
| 54 |
-
.code-editor {
|
| 55 |
-
font-family: 'Monaco', 'Menlo', monospace;
|
| 56 |
-
}
|
| 57 |
-
.metric-card {
|
| 58 |
-
background-color: #1e1e1e;
|
| 59 |
-
padding: 1rem;
|
| 60 |
-
border-radius: 0.5rem;
|
| 61 |
-
border: 1px solid #262730;
|
| 62 |
-
}
|
| 63 |
-
.analysis-section {
|
| 64 |
-
background-color: #1e1e1e;
|
| 65 |
-
padding: 1.5rem;
|
| 66 |
-
border-radius: 0.5rem;
|
| 67 |
-
margin: 1rem 0;
|
| 68 |
-
border: 1px solid #262730;
|
| 69 |
-
}
|
| 70 |
-
.quality-score {
|
| 71 |
-
font-size: 2rem;
|
| 72 |
-
font-weight: bold;
|
| 73 |
-
}
|
| 74 |
-
.model-badge {
|
| 75 |
-
background-color: #262730;
|
| 76 |
-
padding: 0.25rem 0.75rem;
|
| 77 |
-
border-radius: 1rem;
|
| 78 |
-
display: inline-block;
|
| 79 |
-
margin: 0.25rem;
|
| 80 |
-
}
|
| 81 |
-
</style>
|
| 82 |
-
""", unsafe_allow_html=True)
|
| 83 |
-
|
| 84 |
-
# Initialize analyzer with better error handling
|
| 85 |
-
@st.cache_resource
|
| 86 |
-
def get_analyzer():
|
| 87 |
-
try:
|
| 88 |
-
return CodeAnalyzer()
|
| 89 |
-
except Exception as e:
|
| 90 |
-
st.error(f"Failed to initialize analyzer: {str(e)}")
|
| 91 |
-
st.info("Please ensure your API keys are properly configured in the environment variables.")
|
| 92 |
-
return None
|
| 93 |
-
|
| 94 |
-
analyzer = get_analyzer()
|
| 95 |
-
|
| 96 |
-
# Check if analyzer is available
|
| 97 |
-
if analyzer is None:
|
| 98 |
-
st.error("⚠️ Code Analyzer is not available. Please check your API key configuration.")
|
| 99 |
-
st.info("""
|
| 100 |
-
**Required Environment Variables:**
|
| 101 |
-
- `OPENAI_API_KEY` - For OpenAI GPT-4 analysis
|
| 102 |
-
- `ANTHROPIC_API_KEY` - For Claude analysis
|
| 103 |
-
- `DEEPSEEK_API_KEY` - For DeepSeek analysis
|
| 104 |
-
|
| 105 |
-
At least one API key is required for the application to work.
|
| 106 |
-
""")
|
| 107 |
-
st.stop()
|
| 108 |
-
|
| 109 |
-
def display_analysis_result(result: dict, model_name: str):
|
| 110 |
-
"""Display analysis result in a formatted way."""
|
| 111 |
-
if 'error' in result:
|
| 112 |
-
st.error(f"Analysis failed: {result['error']}")
|
| 113 |
-
return
|
| 114 |
-
|
| 115 |
-
# Quality score with color
|
| 116 |
-
score = result['quality_score']
|
| 117 |
-
score_color = "#00ff00" if score >= 80 else "#ffaa00" if score >= 60 else "#ff4444"
|
| 118 |
-
|
| 119 |
-
st.markdown(f"""
|
| 120 |
-
<div class="analysis-section">
|
| 121 |
-
<h3>{model_name}</h3>
|
| 122 |
-
<div style="display: flex; justify-content: space-between; align-items: center;">
|
| 123 |
-
<div>
|
| 124 |
-
<span class="quality-score" style="color: {score_color};">{score}/100</span>
|
| 125 |
-
<p style="margin: 0; color: #888;">Quality Score</p>
|
| 126 |
-
</div>
|
| 127 |
-
<div style="text-align: right;">
|
| 128 |
-
<p style="margin: 0;"><strong>Language:</strong> {result['language']}</p>
|
| 129 |
-
<p style="margin: 0;"><strong>Analysis Time:</strong> {result['execution_time']}s</p>
|
| 130 |
-
</div>
|
| 131 |
-
</div>
|
| 132 |
-
</div>
|
| 133 |
-
""", unsafe_allow_html=True)
|
| 134 |
-
|
| 135 |
-
# Summary
|
| 136 |
-
if result.get('summary'):
|
| 137 |
-
st.markdown("#### 📋 Summary")
|
| 138 |
-
st.info(result['summary'])
|
| 139 |
-
|
| 140 |
-
# Create columns for different sections
|
| 141 |
-
col1, col2 = st.columns(2)
|
| 142 |
-
|
| 143 |
-
with col1:
|
| 144 |
-
# Strengths
|
| 145 |
-
if result.get('strengths'):
|
| 146 |
-
st.markdown("#### ✅ Strengths")
|
| 147 |
-
for strength in result['strengths']:
|
| 148 |
-
st.success(f"• {strength}")
|
| 149 |
-
|
| 150 |
-
# Suggestions
|
| 151 |
-
if result.get('suggestions'):
|
| 152 |
-
st.markdown("#### 💡 Suggestions")
|
| 153 |
-
for suggestion in result['suggestions']:
|
| 154 |
-
st.info(f"• {suggestion}")
|
| 155 |
-
|
| 156 |
-
with col2:
|
| 157 |
-
# Issues
|
| 158 |
-
if result.get('issues'):
|
| 159 |
-
st.markdown("#### ⚠️ Issues")
|
| 160 |
-
for issue in result['issues']:
|
| 161 |
-
st.warning(f"• {issue}")
|
| 162 |
-
|
| 163 |
-
# Security concerns
|
| 164 |
-
if result.get('security_concerns'):
|
| 165 |
-
st.markdown("#### 🔒 Security")
|
| 166 |
-
for concern in result['security_concerns']:
|
| 167 |
-
st.error(f"• {concern}")
|
| 168 |
-
|
| 169 |
-
# Performance notes
|
| 170 |
-
if result.get('performance_notes'):
|
| 171 |
-
st.markdown("#### ⚡ Performance")
|
| 172 |
-
for note in result['performance_notes']:
|
| 173 |
-
st.info(f"• {note}")
|
| 174 |
-
|
| 175 |
-
# Expandable raw response
|
| 176 |
-
with st.expander("View Raw Response"):
|
| 177 |
-
st.code(result.get('raw_response', 'No raw response available'))
|
| 178 |
-
|
| 179 |
-
# Header
|
| 180 |
-
st.title("🔍 Professional Code Analyzer")
|
| 181 |
-
st.markdown("Analyze your code with multiple state-of-the-art LLMs")
|
| 182 |
-
|
| 183 |
-
# Sidebar
|
| 184 |
-
with st.sidebar:
|
| 185 |
-
st.header("⚙️ Configuration")
|
| 186 |
-
|
| 187 |
-
# Model status
|
| 188 |
-
st.subheader("Available Models")
|
| 189 |
-
available_models = analyzer.available_models
|
| 190 |
-
|
| 191 |
-
if not available_models:
|
| 192 |
-
st.error("No models available. Please check your API keys in .env file")
|
| 193 |
-
st.stop()
|
| 194 |
-
|
| 195 |
-
for model, display_name in available_models.items():
|
| 196 |
-
st.success(f"✅ {display_name}")
|
| 197 |
-
|
| 198 |
-
st.divider()
|
| 199 |
-
|
| 200 |
-
# Analysis options
|
| 201 |
-
st.subheader("Analysis Options")
|
| 202 |
-
|
| 203 |
-
# This entire block will only render if models are available
|
| 204 |
-
if available_models:
|
| 205 |
-
selected_model = st.selectbox(
|
| 206 |
-
"Select Model",
|
| 207 |
-
options=list(available_models.keys()),
|
| 208 |
-
format_func=lambda x: available_models[x]
|
| 209 |
-
)
|
| 210 |
-
|
| 211 |
-
analyze_all = st.checkbox("Compare All Models", value=False)
|
| 212 |
-
|
| 213 |
-
# Language selection
|
| 214 |
-
languages = ["auto-detect", "python", "javascript", "java", "cpp", "csharp", "go", "rust"]
|
| 215 |
-
selected_language = st.selectbox("Language", languages)
|
| 216 |
-
else:
|
| 217 |
-
# This message is shown if no models are configured
|
| 218 |
-
st.warning("No models configured. Please add API keys in your environment variables on Render to enable analysis options.")
|
| 219 |
-
|
| 220 |
-
st.divider()
|
| 221 |
-
|
| 222 |
-
# Sample code
|
| 223 |
-
st.subheader("Sample Code")
|
| 224 |
-
if st.button("Load Python Example"):
|
| 225 |
-
st.session_state.code_input = """def fibonacci(n):
|
| 226 |
-
if n <= 1:
|
| 227 |
-
return n
|
| 228 |
-
else:
|
| 229 |
-
return fibonacci(n-1) + fibonacci(n-2)
|
| 230 |
-
|
| 231 |
-
# Calculate fibonacci numbers
|
| 232 |
-
for i in range(10):
|
| 233 |
-
print(f"F({i}) = {fibonacci(i)}")
|
| 234 |
-
"""
|
| 235 |
-
|
| 236 |
-
if st.button("Load JavaScript Example"):
|
| 237 |
-
st.session_state.code_input = """function findDuplicates(arr) {
|
| 238 |
-
let duplicates = [];
|
| 239 |
-
for (let i = 0; i < arr.length; i++) {
|
| 240 |
-
for (let j = i + 1; j < arr.length; j++) {
|
| 241 |
-
if (arr[i] === arr[j]) {
|
| 242 |
-
duplicates.push(arr[i]);
|
| 243 |
-
}
|
| 244 |
-
}
|
| 245 |
-
}
|
| 246 |
-
return duplicates;
|
| 247 |
-
}
|
| 248 |
-
|
| 249 |
-
console.log(findDuplicates([1, 2, 3, 2, 4, 3, 5]));
|
| 250 |
-
"""
|
| 251 |
-
|
| 252 |
-
# Main content
|
| 253 |
-
col1, col2 = st.columns([1, 1])
|
| 254 |
-
|
| 255 |
-
with col1:
|
| 256 |
-
st.subheader("📝 Code Input")
|
| 257 |
-
code_input = st.text_area(
|
| 258 |
-
"Paste your code here",
|
| 259 |
-
value=st.session_state.get('code_input', ''),
|
| 260 |
-
height=400,
|
| 261 |
-
key="code_input",
|
| 262 |
-
help="Paste the code you want to analyze"
|
| 263 |
-
)
|
| 264 |
-
|
| 265 |
-
# Analysis button
|
| 266 |
-
analyze_button = st.button(
|
| 267 |
-
"🚀 Analyze Code",
|
| 268 |
-
type="primary",
|
| 269 |
-
disabled=not code_input.strip()
|
| 270 |
-
)
|
| 271 |
-
|
| 272 |
-
# Results column
|
| 273 |
-
with col2:
|
| 274 |
-
st.subheader("📊 Analysis Results")
|
| 275 |
-
|
| 276 |
-
if analyze_button and code_input.strip():
|
| 277 |
-
with st.spinner("Analyzing code..."):
|
| 278 |
-
if analyze_all:
|
| 279 |
-
# Multi-model analysis
|
| 280 |
-
results = analyzer.analyze_with_all_models(
|
| 281 |
-
code_input,
|
| 282 |
-
selected_language if selected_language != "auto-detect" else None
|
| 283 |
-
)
|
| 284 |
-
|
| 285 |
-
# Display comparison
|
| 286 |
-
comparison = analyzer.compare_analyses(results)
|
| 287 |
-
|
| 288 |
-
# Metrics row
|
| 289 |
-
metrics_cols = st.columns(4)
|
| 290 |
-
with metrics_cols[0]:
|
| 291 |
-
st.metric("Average Score", f"{comparison['average_score']}/100")
|
| 292 |
-
with metrics_cols[1]:
|
| 293 |
-
st.metric("Models Used", len(results))
|
| 294 |
-
with metrics_cols[2]:
|
| 295 |
-
st.metric("Best Score", f"{max(comparison['model_scores'].values())}/100")
|
| 296 |
-
with metrics_cols[3]:
|
| 297 |
-
st.metric("Analysis Time", f"{comparison['analysis_time']:.1f}s")
|
| 298 |
-
|
| 299 |
-
# Tabs for each model
|
| 300 |
-
tabs = st.tabs(list(available_models.values()))
|
| 301 |
-
for idx, (model_key, result) in enumerate(results.items()):
|
| 302 |
-
with tabs[idx]:
|
| 303 |
-
display_analysis_result(result, available_models[model_key])
|
| 304 |
-
|
| 305 |
-
# Consensus findings
|
| 306 |
-
if comparison['consensus_issues']:
|
| 307 |
-
st.markdown("### 🤝 Consensus Issues")
|
| 308 |
-
for issue in comparison['consensus_issues']:
|
| 309 |
-
st.warning(f"• {issue}")
|
| 310 |
-
|
| 311 |
-
else:
|
| 312 |
-
# Single model analysis
|
| 313 |
-
result = analyzer.analyze_code(
|
| 314 |
-
code_input,
|
| 315 |
-
selected_model,
|
| 316 |
-
selected_language if selected_language != "auto-detect" else None
|
| 317 |
-
)
|
| 318 |
-
display_analysis_result(result, available_models[selected_model])
|
| 319 |
-
|
| 320 |
-
# Instructions for empty state
|
| 321 |
-
if not code_input.strip() and not analyze_button:
|
| 322 |
-
st.info("""
|
| 323 |
-
👋 **Welcome to the Professional Code Analyzer!**
|
| 324 |
-
|
| 325 |
-
To get started:
|
| 326 |
-
1. Paste your code in the left panel
|
| 327 |
-
2. Select a model or choose "Compare All Models"
|
| 328 |
-
3. Click "Analyze Code" to get comprehensive insights
|
| 329 |
-
|
| 330 |
-
You can also load sample code from the sidebar to try it out!
|
| 331 |
-
""")
|
| 332 |
-
|
| 333 |
-
# Footer
|
| 334 |
-
st.divider()
|
| 335 |
-
st.markdown("""
|
| 336 |
-
<div style="text-align: center; color: #888; padding: 2rem;">
|
| 337 |
-
<p>Built with Streamlit • Powered by OpenAI, Anthropic, Google, and DeepSeek</p>
|
| 338 |
-
<p>Professional Code Analysis Tool</p>
|
| 339 |
-
</div>
|
| 340 |
-
""", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detailed_model_comparison.py
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Detailed Model Comparison Script
|
| 4 |
+
|
| 5 |
+
This script compares CodeT5+ and CodeBERT side by side
|
| 6 |
+
to show exactly how much better each model is for code analysis.
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
import torch
|
| 10 |
+
import time
|
| 11 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM, AutoModelForSeq2SeqLM
|
| 12 |
+
import json
|
| 13 |
+
|
| 14 |
+
def analyze_code_with_model(model_id: str, model_type: str, test_code: str, test_name: str):
|
| 15 |
+
"""
|
| 16 |
+
Analyze code with a specific model and return detailed results.
|
| 17 |
+
"""
|
| 18 |
+
print(f"\n🧪 Testing {test_name}")
|
| 19 |
+
print("=" * 80)
|
| 20 |
+
|
| 21 |
+
start_time = time.time()
|
| 22 |
+
|
| 23 |
+
try:
|
| 24 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 25 |
+
|
| 26 |
+
# Load tokenizer
|
| 27 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 28 |
+
if tokenizer.pad_token is None:
|
| 29 |
+
tokenizer.pad_token = tokenizer.eos_token
|
| 30 |
+
|
| 31 |
+
# Load model
|
| 32 |
+
if model_type == "seq2seq":
|
| 33 |
+
model = AutoModelForSeq2SeqLM.from_pretrained(
|
| 34 |
+
model_id,
|
| 35 |
+
torch_dtype=torch.float16,
|
| 36 |
+
device_map="auto"
|
| 37 |
+
)
|
| 38 |
+
else:
|
| 39 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 40 |
+
model_id,
|
| 41 |
+
torch_dtype=torch.float16,
|
| 42 |
+
device_map="auto"
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
# Get model info
|
| 46 |
+
param_count = sum(p.numel() for p in model.parameters())
|
| 47 |
+
|
| 48 |
+
# Create analysis prompt
|
| 49 |
+
prompt = f"""Analyze this code for bugs, performance issues, and security concerns:
|
| 50 |
+
|
| 51 |
+
{test_code}
|
| 52 |
+
|
| 53 |
+
Analysis:"""
|
| 54 |
+
|
| 55 |
+
# Tokenize
|
| 56 |
+
inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512)
|
| 57 |
+
inputs = {k: v.to(device) for k, v in inputs.items()}
|
| 58 |
+
|
| 59 |
+
# Generate analysis
|
| 60 |
+
generation_start = time.time()
|
| 61 |
+
with torch.no_grad():
|
| 62 |
+
if model_type == "seq2seq":
|
| 63 |
+
outputs = model.generate(
|
| 64 |
+
inputs["input_ids"],
|
| 65 |
+
max_length=inputs["input_ids"].shape[1] + 300,
|
| 66 |
+
num_beams=4,
|
| 67 |
+
early_stopping=True,
|
| 68 |
+
do_sample=False,
|
| 69 |
+
temperature=0.7
|
| 70 |
+
)
|
| 71 |
+
else:
|
| 72 |
+
outputs = model.generate(
|
| 73 |
+
inputs["input_ids"],
|
| 74 |
+
max_length=inputs["input_ids"].shape[1] + 300,
|
| 75 |
+
temperature=0.7,
|
| 76 |
+
do_sample=True,
|
| 77 |
+
pad_token_id=tokenizer.eos_token_id,
|
| 78 |
+
top_p=0.9
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
generation_time = time.time() - generation_start
|
| 82 |
+
|
| 83 |
+
# Decode analysis
|
| 84 |
+
analysis = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 85 |
+
analysis_text = analysis[len(prompt):].strip()
|
| 86 |
+
|
| 87 |
+
total_time = time.time() - start_time
|
| 88 |
+
|
| 89 |
+
# Analyze the quality of the analysis
|
| 90 |
+
quality_score = analyze_analysis_quality(analysis_text, test_code)
|
| 91 |
+
|
| 92 |
+
return {
|
| 93 |
+
"model_id": model_id,
|
| 94 |
+
"model_type": model_type,
|
| 95 |
+
"test_name": test_name,
|
| 96 |
+
"success": True,
|
| 97 |
+
"analysis": analysis_text,
|
| 98 |
+
"total_time": total_time,
|
| 99 |
+
"generation_time": generation_time,
|
| 100 |
+
"parameters": param_count,
|
| 101 |
+
"quality_score": quality_score,
|
| 102 |
+
"analysis_length": len(analysis_text)
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
except Exception as e:
|
| 106 |
+
return {
|
| 107 |
+
"model_id": model_id,
|
| 108 |
+
"model_type": model_type,
|
| 109 |
+
"test_name": test_name,
|
| 110 |
+
"success": False,
|
| 111 |
+
"error": str(e),
|
| 112 |
+
"total_time": time.time() - start_time
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
def analyze_analysis_quality(analysis_text: str, original_code: str):
|
| 116 |
+
"""
|
| 117 |
+
Analyze the quality of the code analysis.
|
| 118 |
+
Returns a score from 0-100 based on various factors.
|
| 119 |
+
"""
|
| 120 |
+
score = 0
|
| 121 |
+
|
| 122 |
+
# Check for different types of analysis
|
| 123 |
+
analysis_lower = analysis_text.lower()
|
| 124 |
+
|
| 125 |
+
# Bug detection (20 points)
|
| 126 |
+
if any(word in analysis_lower for word in ['bug', 'error', 'issue', 'problem', 'flaw']):
|
| 127 |
+
score += 20
|
| 128 |
+
|
| 129 |
+
# Performance analysis (20 points)
|
| 130 |
+
if any(word in analysis_lower for word in ['performance', 'slow', 'efficient', 'complexity', 'optimization']):
|
| 131 |
+
score += 20
|
| 132 |
+
|
| 133 |
+
# Security analysis (20 points)
|
| 134 |
+
if any(word in analysis_lower for word in ['security', 'vulnerability', 'safe', 'unsafe', 'risk']):
|
| 135 |
+
score += 20
|
| 136 |
+
|
| 137 |
+
# Code structure analysis (20 points)
|
| 138 |
+
if any(word in analysis_lower for word in ['structure', 'design', 'pattern', 'architecture', 'organization']):
|
| 139 |
+
score += 20
|
| 140 |
+
|
| 141 |
+
# Suggestions/improvements (20 points)
|
| 142 |
+
if any(word in analysis_lower for word in ['suggest', 'improve', 'better', 'recommend', 'fix', 'solution']):
|
| 143 |
+
score += 20
|
| 144 |
+
|
| 145 |
+
# Bonus points for detailed analysis
|
| 146 |
+
if len(analysis_text) > 200:
|
| 147 |
+
score += 10
|
| 148 |
+
if len(analysis_text) > 500:
|
| 149 |
+
score += 10
|
| 150 |
+
|
| 151 |
+
return min(score, 100)
|
| 152 |
+
|
| 153 |
+
def compare_models():
|
| 154 |
+
"""
|
| 155 |
+
Compare CodeT5+ and CodeBERT on multiple test cases.
|
| 156 |
+
"""
|
| 157 |
+
|
| 158 |
+
# Test cases with different types of code issues
|
| 159 |
+
test_cases = [
|
| 160 |
+
{
|
| 161 |
+
"name": "Performance Issue (Recursive Fibonacci)",
|
| 162 |
+
"code": """
|
| 163 |
+
def calculate_fibonacci(n):
|
| 164 |
+
if n <= 0:
|
| 165 |
+
return 0
|
| 166 |
+
elif n == 1:
|
| 167 |
+
return 1
|
| 168 |
+
else:
|
| 169 |
+
return calculate_fibonacci(n-1) + calculate_fibonacci(n-2)
|
| 170 |
+
|
| 171 |
+
# This will be slow for large numbers
|
| 172 |
+
result = calculate_fibonacci(35)
|
| 173 |
+
print(result)
|
| 174 |
+
"""
|
| 175 |
+
},
|
| 176 |
+
{
|
| 177 |
+
"name": "Security Issue (SQL Injection)",
|
| 178 |
+
"code": """
|
| 179 |
+
import sqlite3
|
| 180 |
+
|
| 181 |
+
def get_user(email):
|
| 182 |
+
conn = sqlite3.connect("app.db")
|
| 183 |
+
cur = conn.cursor()
|
| 184 |
+
# vulnerable string interpolation
|
| 185 |
+
q = f"SELECT id, email, role FROM users WHERE email = '{email}'"
|
| 186 |
+
rows = cur.execute(q).fetchall()
|
| 187 |
+
conn.close()
|
| 188 |
+
return rows[0] if rows else None
|
| 189 |
+
|
| 190 |
+
# Usage
|
| 191 |
+
user = get_user("admin@example.com")
|
| 192 |
+
"""
|
| 193 |
+
},
|
| 194 |
+
{
|
| 195 |
+
"name": "Bug Issue (Division by Zero)",
|
| 196 |
+
"code": """
|
| 197 |
+
def divide_numbers(a, b):
|
| 198 |
+
return a / b
|
| 199 |
+
|
| 200 |
+
def calculate_average(numbers):
|
| 201 |
+
total = sum(numbers)
|
| 202 |
+
count = len(numbers)
|
| 203 |
+
return divide_numbers(total, count)
|
| 204 |
+
|
| 205 |
+
# This will crash with empty list
|
| 206 |
+
result = calculate_average([])
|
| 207 |
+
print(result)
|
| 208 |
+
"""
|
| 209 |
+
}
|
| 210 |
+
]
|
| 211 |
+
|
| 212 |
+
# Models to compare
|
| 213 |
+
models = [
|
| 214 |
+
{
|
| 215 |
+
"id": "Salesforce/codet5p-220m",
|
| 216 |
+
"type": "seq2seq",
|
| 217 |
+
"name": "CodeT5+ (Recommended)"
|
| 218 |
+
},
|
| 219 |
+
{
|
| 220 |
+
"id": "microsoft/CodeBERT-base",
|
| 221 |
+
"type": "causal",
|
| 222 |
+
"name": "CodeBERT (Alternative)"
|
| 223 |
+
}
|
| 224 |
+
]
|
| 225 |
+
|
| 226 |
+
print("🚀 DETAILED MODEL COMPARISON")
|
| 227 |
+
print("=" * 100)
|
| 228 |
+
print("Testing both models on multiple code analysis scenarios...")
|
| 229 |
+
|
| 230 |
+
all_results = []
|
| 231 |
+
|
| 232 |
+
for test_case in test_cases:
|
| 233 |
+
print(f"\n📋 TEST CASE: {test_case['name']}")
|
| 234 |
+
print("=" * 100)
|
| 235 |
+
print(f"Code to analyze:\n{test_case['code']}")
|
| 236 |
+
print("=" * 100)
|
| 237 |
+
|
| 238 |
+
test_results = []
|
| 239 |
+
|
| 240 |
+
for model in models:
|
| 241 |
+
result = analyze_code_with_model(
|
| 242 |
+
model["id"],
|
| 243 |
+
model["type"],
|
| 244 |
+
test_case["code"],
|
| 245 |
+
model["name"]
|
| 246 |
+
)
|
| 247 |
+
test_results.append(result)
|
| 248 |
+
all_results.append(result)
|
| 249 |
+
|
| 250 |
+
# Show side-by-side comparison for this test case
|
| 251 |
+
print(f"\n📊 SIDE-BY-SIDE COMPARISON:")
|
| 252 |
+
print("-" * 100)
|
| 253 |
+
|
| 254 |
+
for result in test_results:
|
| 255 |
+
if result["success"]:
|
| 256 |
+
print(f"\n🤖 {result['test_name']}:")
|
| 257 |
+
print(f" ⏱️ Time: {result['total_time']:.2f}s")
|
| 258 |
+
print(f" 📊 Parameters: {result['parameters']:,}")
|
| 259 |
+
print(f" 🎯 Quality Score: {result['quality_score']}/100")
|
| 260 |
+
print(f" 📝 Analysis Length: {result['analysis_length']} chars")
|
| 261 |
+
print(f" 📄 Analysis:")
|
| 262 |
+
print(f" {result['analysis'][:200]}{'...' if len(result['analysis']) > 200 else ''}")
|
| 263 |
+
else:
|
| 264 |
+
print(f"\n❌ {result['test_name']}: FAILED - {result['error']}")
|
| 265 |
+
|
| 266 |
+
# Overall comparison
|
| 267 |
+
print(f"\n🏆 OVERALL COMPARISON SUMMARY")
|
| 268 |
+
print("=" * 100)
|
| 269 |
+
|
| 270 |
+
# Group results by model
|
| 271 |
+
codet5_results = [r for r in all_results if r.get("model_id") == "Salesforce/codet5p-220m" and r["success"]]
|
| 272 |
+
codebert_results = [r for r in all_results if r.get("model_id") == "microsoft/CodeBERT-base" and r["success"]]
|
| 273 |
+
|
| 274 |
+
if codet5_results and codebert_results:
|
| 275 |
+
# Calculate averages
|
| 276 |
+
codet5_avg_time = sum(r["total_time"] for r in codet5_results) / len(codet5_results)
|
| 277 |
+
codet5_avg_quality = sum(r["quality_score"] for r in codet5_results) / len(codet5_results)
|
| 278 |
+
codet5_avg_length = sum(r["analysis_length"] for r in codet5_results) / len(codet5_results)
|
| 279 |
+
|
| 280 |
+
codebert_avg_time = sum(r["total_time"] for r in codebert_results) / len(codebert_results)
|
| 281 |
+
codebert_avg_quality = sum(r["quality_score"] for r in codebert_results) / len(codebert_results)
|
| 282 |
+
codebert_avg_length = sum(r["analysis_length"] for r in codebert_results) / len(codebert_results)
|
| 283 |
+
|
| 284 |
+
print(f"\n📈 AVERAGE PERFORMANCE:")
|
| 285 |
+
print(f"CodeT5+:")
|
| 286 |
+
print(f" ⏱️ Time: {codet5_avg_time:.2f}s")
|
| 287 |
+
print(f" 🎯 Quality: {codet5_avg_quality:.1f}/100")
|
| 288 |
+
print(f" 📝 Length: {codet5_avg_length:.0f} chars")
|
| 289 |
+
|
| 290 |
+
print(f"\nCodeBERT:")
|
| 291 |
+
print(f" ⏱️ Time: {codebert_avg_time:.2f}s")
|
| 292 |
+
print(f" 🎯 Quality: {codebert_avg_quality:.1f}/100")
|
| 293 |
+
print(f" 📝 Length: {codebert_avg_length:.0f} chars")
|
| 294 |
+
|
| 295 |
+
# Calculate improvements
|
| 296 |
+
time_ratio = codebert_avg_time / codet5_avg_time
|
| 297 |
+
quality_diff = codet5_avg_quality - codebert_avg_quality
|
| 298 |
+
length_ratio = codet5_avg_length / codebert_avg_length
|
| 299 |
+
|
| 300 |
+
print(f"\n🎯 IMPROVEMENT ANALYSIS:")
|
| 301 |
+
print(f"Speed: CodeBERT is {time_ratio:.1f}x faster than CodeT5+")
|
| 302 |
+
print(f"Quality: CodeT5+ is {quality_diff:.1f} points better than CodeBERT")
|
| 303 |
+
print(f"Detail: CodeT5+ gives {length_ratio:.1f}x more detailed analysis")
|
| 304 |
+
|
| 305 |
+
# Final recommendation
|
| 306 |
+
print(f"\n🏆 FINAL RECOMMENDATION:")
|
| 307 |
+
if quality_diff > 10:
|
| 308 |
+
print(f"✅ Use CodeT5+ - Significantly better analysis quality ({quality_diff:.1f} points better)")
|
| 309 |
+
print(f" Trade-off: {time_ratio:.1f}x slower, but much better results")
|
| 310 |
+
elif quality_diff > 5:
|
| 311 |
+
print(f"✅ Use CodeT5+ - Better analysis quality ({quality_diff:.1f} points better)")
|
| 312 |
+
print(f" Trade-off: {time_ratio:.1f}x slower, but better results")
|
| 313 |
+
else:
|
| 314 |
+
print(f"🤔 Both models are similar in quality")
|
| 315 |
+
print(f" Choose CodeBERT for speed, CodeT5+ for slightly better quality")
|
| 316 |
+
|
| 317 |
+
def main():
|
| 318 |
+
"""
|
| 319 |
+
Main function to run the detailed comparison.
|
| 320 |
+
"""
|
| 321 |
+
compare_models()
|
| 322 |
+
|
| 323 |
+
if __name__ == "__main__":
|
| 324 |
+
main()
|
finetune.py
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Fine-tuning Script for AI Code Analyzer
|
| 4 |
+
|
| 5 |
+
This script fine-tunes the DeepSeek Coder model using QLoRA (Quantized LoRA)
|
| 6 |
+
technique on our custom code analysis dataset.
|
| 7 |
+
|
| 8 |
+
Features:
|
| 9 |
+
- 4-bit quantization for memory efficiency
|
| 10 |
+
- LoRA adapters for parameter-efficient fine-tuning
|
| 11 |
+
- Supervised Fine-Tuning (SFT) using TRL
|
| 12 |
+
- Automatic model saving and adapter persistence
|
| 13 |
+
|
| 14 |
+
Author: AI Code Analyzer Project
|
| 15 |
+
Date: 2025
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
import os
|
| 19 |
+
import argparse
|
| 20 |
+
import torch
|
| 21 |
+
from transformers import (
|
| 22 |
+
AutoModelForCausalLM,
|
| 23 |
+
AutoTokenizer,
|
| 24 |
+
BitsAndBytesConfig,
|
| 25 |
+
TrainingArguments,
|
| 26 |
+
DataCollatorForLanguageModeling
|
| 27 |
+
)
|
| 28 |
+
from peft import LoraConfig, get_peft_model, TaskType
|
| 29 |
+
from trl import SFTTrainer
|
| 30 |
+
from datasets import Dataset
|
| 31 |
+
import json
|
| 32 |
+
import logging
|
| 33 |
+
|
| 34 |
+
# Set up logging
|
| 35 |
+
logging.basicConfig(level=logging.INFO)
|
| 36 |
+
logger = logging.getLogger(__name__)
|
| 37 |
+
|
| 38 |
+
def load_dataset(file_path: str) -> Dataset:
|
| 39 |
+
"""
|
| 40 |
+
Load the training dataset from JSONL file.
|
| 41 |
+
|
| 42 |
+
Args:
|
| 43 |
+
file_path (str): Path to the analyst_dataset.jsonl file
|
| 44 |
+
|
| 45 |
+
Returns:
|
| 46 |
+
Dataset: Hugging Face dataset object
|
| 47 |
+
"""
|
| 48 |
+
logger.info(f"Loading dataset from {file_path}")
|
| 49 |
+
|
| 50 |
+
data = []
|
| 51 |
+
with open(file_path, 'r', encoding='utf-8') as f:
|
| 52 |
+
for line in f:
|
| 53 |
+
if line.strip():
|
| 54 |
+
data.append(json.loads(line))
|
| 55 |
+
|
| 56 |
+
logger.info(f"Loaded {len(data)} training samples")
|
| 57 |
+
return Dataset.from_list(data)
|
| 58 |
+
|
| 59 |
+
def create_quantization_config() -> BitsAndBytesConfig:
|
| 60 |
+
"""
|
| 61 |
+
Create 4-bit quantization configuration for memory efficiency.
|
| 62 |
+
|
| 63 |
+
Returns:
|
| 64 |
+
BitsAndBytesConfig: Quantization configuration
|
| 65 |
+
"""
|
| 66 |
+
logger.info("Creating 4-bit quantization configuration")
|
| 67 |
+
|
| 68 |
+
return BitsAndBytesConfig(
|
| 69 |
+
load_in_4bit=True,
|
| 70 |
+
bnb_4bit_quant_type="nf4",
|
| 71 |
+
bnb_4bit_compute_dtype=torch.float16,
|
| 72 |
+
bnb_4bit_use_double_quant=True,
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
def infer_lora_target_modules(model) -> list[str]:
|
| 76 |
+
"""Infer suitable LoRA target modules by inspecting model modules.
|
| 77 |
+
|
| 78 |
+
Handles common architectures:
|
| 79 |
+
- LLaMA/DeepSeek-like: q_proj,k_proj,v_proj,o_proj,gate_proj,up_proj,down_proj
|
| 80 |
+
- GPT-2/OPT-like: c_attn,c_proj,c_fc (when present)
|
| 81 |
+
Falls back to any module names that contain 'q_proj','k_proj','v_proj','o_proj'
|
| 82 |
+
found in the model.
|
| 83 |
+
"""
|
| 84 |
+
llama_like = ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]
|
| 85 |
+
gpt2_like = ["c_attn", "c_proj", "c_fc"]
|
| 86 |
+
|
| 87 |
+
module_names = set(name.split(".")[-1] for name, _ in model.named_modules())
|
| 88 |
+
|
| 89 |
+
if any(m in module_names for m in llama_like):
|
| 90 |
+
return [m for m in llama_like if m in module_names]
|
| 91 |
+
|
| 92 |
+
if any(m in module_names for m in gpt2_like):
|
| 93 |
+
return [m for m in gpt2_like if m in module_names]
|
| 94 |
+
|
| 95 |
+
# Generic attention projection fallback
|
| 96 |
+
generic = [m for m in ["q_proj", "k_proj", "v_proj", "o_proj"] if m in module_names]
|
| 97 |
+
if generic:
|
| 98 |
+
return generic
|
| 99 |
+
|
| 100 |
+
# Last resort: try any modules containing 'attn' or 'proj'
|
| 101 |
+
heuristic = [m for m in module_names if ("attn" in m or "proj" in m)]
|
| 102 |
+
return heuristic[:4] if heuristic else []
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
def create_lora_config(model) -> LoraConfig:
|
| 106 |
+
"""
|
| 107 |
+
Create LoRA configuration for parameter-efficient fine-tuning.
|
| 108 |
+
|
| 109 |
+
Returns:
|
| 110 |
+
LoraConfig: LoRA configuration
|
| 111 |
+
"""
|
| 112 |
+
logger.info("Creating LoRA configuration")
|
| 113 |
+
|
| 114 |
+
target_modules = infer_lora_target_modules(model)
|
| 115 |
+
if not target_modules:
|
| 116 |
+
logger.warning("Could not infer LoRA target modules; proceeding without explicit targets (may fail)")
|
| 117 |
+
target_modules = None # Let PEFT attempt defaults
|
| 118 |
+
|
| 119 |
+
return LoraConfig(
|
| 120 |
+
task_type=TaskType.CAUSAL_LM,
|
| 121 |
+
inference_mode=False,
|
| 122 |
+
r=16, # Rank of adaptation
|
| 123 |
+
lora_alpha=32, # LoRA scaling parameter
|
| 124 |
+
lora_dropout=0.1, # LoRA dropout
|
| 125 |
+
target_modules=target_modules,
|
| 126 |
+
)
|
| 127 |
+
|
| 128 |
+
def create_training_arguments(args: argparse.Namespace) -> TrainingArguments:
|
| 129 |
+
"""
|
| 130 |
+
Create training arguments for the fine-tuning process.
|
| 131 |
+
|
| 132 |
+
Returns:
|
| 133 |
+
TrainingArguments: Training configuration
|
| 134 |
+
"""
|
| 135 |
+
logger.info("Creating training arguments")
|
| 136 |
+
|
| 137 |
+
# Defaults
|
| 138 |
+
num_train_epochs = args.epochs if args.epochs is not None else 3
|
| 139 |
+
per_device_train_batch_size = args.batch_size if args.batch_size is not None else 1
|
| 140 |
+
logging_steps = 10
|
| 141 |
+
save_steps = 500
|
| 142 |
+
max_steps = args.max_steps if args.max_steps is not None else -1
|
| 143 |
+
|
| 144 |
+
if args.dry_run:
|
| 145 |
+
# Make the run extremely short and avoid frequent saving
|
| 146 |
+
num_train_epochs = 1 if args.epochs is None else args.epochs
|
| 147 |
+
logging_steps = 1
|
| 148 |
+
save_steps = 10_000_000
|
| 149 |
+
if args.max_steps is None:
|
| 150 |
+
max_steps = 1
|
| 151 |
+
|
| 152 |
+
return TrainingArguments(
|
| 153 |
+
output_dir="./fine-tuned-analyst",
|
| 154 |
+
num_train_epochs=num_train_epochs,
|
| 155 |
+
per_device_train_batch_size=per_device_train_batch_size,
|
| 156 |
+
gradient_accumulation_steps=4,
|
| 157 |
+
warmup_steps=100,
|
| 158 |
+
learning_rate=2e-4,
|
| 159 |
+
fp16=args.fp16,
|
| 160 |
+
logging_steps=logging_steps,
|
| 161 |
+
save_steps=save_steps,
|
| 162 |
+
save_total_limit=2,
|
| 163 |
+
remove_unused_columns=False,
|
| 164 |
+
push_to_hub=False,
|
| 165 |
+
report_to=None, # Disable wandb/tensorboard
|
| 166 |
+
dataloader_pin_memory=False,
|
| 167 |
+
max_steps=max_steps,
|
| 168 |
+
)
|
| 169 |
+
|
| 170 |
+
def main():
|
| 171 |
+
"""
|
| 172 |
+
Main function to execute the fine-tuning process.
|
| 173 |
+
"""
|
| 174 |
+
logger.info("Starting AI Code Analyzer fine-tuning process")
|
| 175 |
+
|
| 176 |
+
parser = argparse.ArgumentParser(description="Fine-tune DeepSeek Coder with QLoRA")
|
| 177 |
+
parser.add_argument("--model", type=str, default="deepseek-ai/deepseek-coder-1.3b-instruct", help="Base model ID (HF Hub)")
|
| 178 |
+
parser.add_argument("--subset", type=int, default=None, help="Use only the first N samples from the dataset")
|
| 179 |
+
parser.add_argument("--epochs", type=int, default=None, help="Number of training epochs")
|
| 180 |
+
parser.add_argument("--batch-size", type=int, default=None, help="Per-device train batch size")
|
| 181 |
+
parser.add_argument("--max-steps", type=int, default=None, help="Override maximum training steps")
|
| 182 |
+
parser.add_argument("--dry-run", action="store_true", help="Run a very short demo training")
|
| 183 |
+
parser.add_argument("--no-quant", action="store_true", help="Disable 4-bit quantization (useful for CPU runs)")
|
| 184 |
+
args = parser.parse_args()
|
| 185 |
+
|
| 186 |
+
# Check if CUDA is available
|
| 187 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 188 |
+
logger.info(f"Using device: {device}")
|
| 189 |
+
if device == "cpu":
|
| 190 |
+
logger.warning("CUDA not available. Training will be slow on CPU.")
|
| 191 |
+
|
| 192 |
+
# Step 1: Load the dataset
|
| 193 |
+
dataset = load_dataset("analyst_dataset.jsonl")
|
| 194 |
+
if args.subset is not None and args.subset > 0:
|
| 195 |
+
logger.info(f"Using only the first {args.subset} samples for this run")
|
| 196 |
+
dataset = dataset.select(range(min(args.subset, len(dataset))))
|
| 197 |
+
|
| 198 |
+
# Step 2: Load the base model and tokenizer
|
| 199 |
+
model_name = args.model
|
| 200 |
+
logger.info(f"Loading model: {model_name}")
|
| 201 |
+
|
| 202 |
+
# Create quantization config if enabled and likely supported
|
| 203 |
+
use_quant = (device == "cuda") and (not args.no_quant)
|
| 204 |
+
quantization_config = create_quantization_config() if use_quant else None
|
| 205 |
+
if not use_quant:
|
| 206 |
+
logger.info("Quantization disabled (CPU or --no-quant). Using standard weights.")
|
| 207 |
+
|
| 208 |
+
# Load tokenizer
|
| 209 |
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 210 |
+
if tokenizer.pad_token is None:
|
| 211 |
+
tokenizer.pad_token = tokenizer.eos_token
|
| 212 |
+
|
| 213 |
+
# Load model with quantization
|
| 214 |
+
if quantization_config is not None:
|
| 215 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 216 |
+
model_name,
|
| 217 |
+
quantization_config=quantization_config,
|
| 218 |
+
device_map="auto",
|
| 219 |
+
trust_remote_code=True,
|
| 220 |
+
)
|
| 221 |
+
fp16 = True
|
| 222 |
+
else:
|
| 223 |
+
# CPU or non-quantized path
|
| 224 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 225 |
+
model_name,
|
| 226 |
+
torch_dtype=torch.float32 if device == "cpu" else torch.float16,
|
| 227 |
+
device_map="cpu" if device == "cpu" else "auto",
|
| 228 |
+
low_cpu_mem_usage=True,
|
| 229 |
+
trust_remote_code=True,
|
| 230 |
+
)
|
| 231 |
+
fp16 = (device != "cpu")
|
| 232 |
+
|
| 233 |
+
# Step 3: Configure LoRA
|
| 234 |
+
lora_config = create_lora_config(model)
|
| 235 |
+
model = get_peft_model(model, lora_config)
|
| 236 |
+
|
| 237 |
+
# Print trainable parameters
|
| 238 |
+
model.print_trainable_parameters()
|
| 239 |
+
|
| 240 |
+
# Step 4: Set training arguments
|
| 241 |
+
# Ensure training args match device precision
|
| 242 |
+
args.fp16 = fp16
|
| 243 |
+
training_args = create_training_arguments(args)
|
| 244 |
+
|
| 245 |
+
# Step 5: Initialize SFT Trainer
|
| 246 |
+
logger.info("Initializing SFT Trainer")
|
| 247 |
+
|
| 248 |
+
# Provide the tokenizer/processor via processing_class
|
| 249 |
+
trainer = SFTTrainer(
|
| 250 |
+
model=model,
|
| 251 |
+
args=training_args,
|
| 252 |
+
train_dataset=dataset,
|
| 253 |
+
processing_class=tokenizer,
|
| 254 |
+
formatting_func=lambda r: r["text"],
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
# Step 6: Start training
|
| 258 |
+
logger.info("Starting training...")
|
| 259 |
+
trainer.train()
|
| 260 |
+
|
| 261 |
+
# Step 7: Save the model
|
| 262 |
+
logger.info("Saving fine-tuned model...")
|
| 263 |
+
trainer.save_model()
|
| 264 |
+
tokenizer.save_pretrained(training_args.output_dir)
|
| 265 |
+
|
| 266 |
+
# Save LoRA adapters separately
|
| 267 |
+
model.save_pretrained(f"{training_args.output_dir}/lora_adapters")
|
| 268 |
+
|
| 269 |
+
logger.info("Fine-tuning completed successfully!")
|
| 270 |
+
logger.info(f"Model saved to: {training_args.output_dir}")
|
| 271 |
+
logger.info("LoRA adapters saved to: {}/lora_adapters".format(training_args.output_dir))
|
| 272 |
+
|
| 273 |
+
if __name__ == "__main__":
|
| 274 |
+
main()
|
finetune_improved.py
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Improved Fine-tuning Script for AI Code Analyzer
|
| 4 |
+
|
| 5 |
+
This script fine-tunes specialized code analysis models using QLoRA technique
|
| 6 |
+
on our custom code analysis dataset.
|
| 7 |
+
|
| 8 |
+
Key Improvements:
|
| 9 |
+
- Uses CodeT5+ or CodeBERT for better code understanding
|
| 10 |
+
- Optimized for code analysis tasks
|
| 11 |
+
- Better tokenization for code
|
| 12 |
+
- Improved training parameters
|
| 13 |
+
|
| 14 |
+
Author: AI Code Analyzer Project
|
| 15 |
+
Date: 2025
|
| 16 |
+
"""
|
| 17 |
+
|
| 18 |
+
import os
|
| 19 |
+
import argparse
|
| 20 |
+
import torch
|
| 21 |
+
from transformers import (
|
| 22 |
+
AutoModelForCausalLM,
|
| 23 |
+
AutoModelForSeq2SeqLM, # For CodeT5 models
|
| 24 |
+
AutoTokenizer,
|
| 25 |
+
BitsAndBytesConfig,
|
| 26 |
+
TrainingArguments,
|
| 27 |
+
DataCollatorForLanguageModeling
|
| 28 |
+
)
|
| 29 |
+
from peft import LoraConfig, get_peft_model, TaskType
|
| 30 |
+
from trl import SFTTrainer
|
| 31 |
+
from datasets import Dataset
|
| 32 |
+
import json
|
| 33 |
+
import logging
|
| 34 |
+
|
| 35 |
+
# Set up logging
|
| 36 |
+
logging.basicConfig(level=logging.INFO)
|
| 37 |
+
logger = logging.getLogger(__name__)
|
| 38 |
+
|
| 39 |
+
def load_dataset(file_path: str) -> Dataset:
|
| 40 |
+
"""
|
| 41 |
+
Load the training dataset from JSONL file.
|
| 42 |
+
|
| 43 |
+
Args:
|
| 44 |
+
file_path (str): Path to the analyst_dataset.jsonl file
|
| 45 |
+
|
| 46 |
+
Returns:
|
| 47 |
+
Dataset: Hugging Face dataset object
|
| 48 |
+
"""
|
| 49 |
+
logger.info(f"Loading dataset from {file_path}")
|
| 50 |
+
|
| 51 |
+
data = []
|
| 52 |
+
with open(file_path, 'r', encoding='utf-8') as f:
|
| 53 |
+
for line in f:
|
| 54 |
+
if line.strip():
|
| 55 |
+
data.append(json.loads(line))
|
| 56 |
+
|
| 57 |
+
logger.info(f"Loaded {len(data)} training samples")
|
| 58 |
+
return Dataset.from_list(data)
|
| 59 |
+
|
| 60 |
+
def create_quantization_config() -> BitsAndBytesConfig:
|
| 61 |
+
"""
|
| 62 |
+
Create 4-bit quantization configuration for memory efficiency.
|
| 63 |
+
|
| 64 |
+
Returns:
|
| 65 |
+
BitsAndBytesConfig: Quantization configuration
|
| 66 |
+
"""
|
| 67 |
+
logger.info("Creating 4-bit quantization configuration")
|
| 68 |
+
|
| 69 |
+
return BitsAndBytesConfig(
|
| 70 |
+
load_in_4bit=True,
|
| 71 |
+
bnb_4bit_quant_type="nf4",
|
| 72 |
+
bnb_4bit_compute_dtype=torch.float16,
|
| 73 |
+
bnb_4bit_use_double_quant=True,
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
def get_model_class(model_name: str):
|
| 77 |
+
"""
|
| 78 |
+
Determine the appropriate model class based on the model name.
|
| 79 |
+
|
| 80 |
+
Args:
|
| 81 |
+
model_name (str): Name of the model
|
| 82 |
+
|
| 83 |
+
Returns:
|
| 84 |
+
Model class: Appropriate model class for the given model
|
| 85 |
+
"""
|
| 86 |
+
if "codet5" in model_name.lower():
|
| 87 |
+
logger.info(f"Using Seq2SeqLM for CodeT5 model: {model_name}")
|
| 88 |
+
return AutoModelForSeq2SeqLM
|
| 89 |
+
else:
|
| 90 |
+
logger.info(f"Using CausalLM for model: {model_name}")
|
| 91 |
+
return AutoModelForCausalLM
|
| 92 |
+
|
| 93 |
+
def create_lora_config(model_name: str) -> LoraConfig:
|
| 94 |
+
"""
|
| 95 |
+
Create LoRA configuration optimized for code analysis models.
|
| 96 |
+
|
| 97 |
+
Args:
|
| 98 |
+
model_name (str): Name of the base model
|
| 99 |
+
|
| 100 |
+
Returns:
|
| 101 |
+
LoraConfig: LoRA configuration
|
| 102 |
+
"""
|
| 103 |
+
logger.info(f"Creating LoRA configuration for {model_name}")
|
| 104 |
+
|
| 105 |
+
# Different target modules for different model architectures
|
| 106 |
+
if "codet5" in model_name.lower():
|
| 107 |
+
# CodeT5 architecture
|
| 108 |
+
target_modules = ["q", "v", "k", "o", "wi_0", "wi_1", "wo"]
|
| 109 |
+
task_type = TaskType.SEQ_2_SEQ_LM
|
| 110 |
+
elif "codebert" in model_name.lower():
|
| 111 |
+
# CodeBERT architecture
|
| 112 |
+
target_modules = ["query", "key", "value", "dense"]
|
| 113 |
+
task_type = TaskType.FEATURE_EXTRACTION
|
| 114 |
+
else:
|
| 115 |
+
# Default for most causal LM models
|
| 116 |
+
target_modules = ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"]
|
| 117 |
+
task_type = TaskType.CAUSAL_LM
|
| 118 |
+
|
| 119 |
+
return LoraConfig(
|
| 120 |
+
r=16,
|
| 121 |
+
lora_alpha=32,
|
| 122 |
+
target_modules=target_modules,
|
| 123 |
+
lora_dropout=0.1,
|
| 124 |
+
bias="none",
|
| 125 |
+
task_type=task_type,
|
| 126 |
+
)
|
| 127 |
+
|
| 128 |
+
def create_training_arguments(args) -> TrainingArguments:
|
| 129 |
+
"""
|
| 130 |
+
Create training arguments optimized for code analysis fine-tuning.
|
| 131 |
+
|
| 132 |
+
Args:
|
| 133 |
+
args: Command line arguments
|
| 134 |
+
|
| 135 |
+
Returns:
|
| 136 |
+
TrainingArguments: Training configuration
|
| 137 |
+
"""
|
| 138 |
+
# Calculate training parameters
|
| 139 |
+
num_train_epochs = args.epochs if args.epochs else 3
|
| 140 |
+
per_device_train_batch_size = args.batch_size if args.batch_size else 2
|
| 141 |
+
logging_steps = 10
|
| 142 |
+
save_steps = 500
|
| 143 |
+
|
| 144 |
+
# For demo runs
|
| 145 |
+
if args.dry_run:
|
| 146 |
+
logger.info("Running in dry-run mode with minimal training")
|
| 147 |
+
num_train_epochs = 1
|
| 148 |
+
per_device_train_batch_size = 1
|
| 149 |
+
max_steps = 1
|
| 150 |
+
|
| 151 |
+
return TrainingArguments(
|
| 152 |
+
output_dir="./fine-tuned-analyst-improved",
|
| 153 |
+
num_train_epochs=num_train_epochs,
|
| 154 |
+
per_device_train_batch_size=per_device_train_batch_size,
|
| 155 |
+
gradient_accumulation_steps=4,
|
| 156 |
+
warmup_steps=100,
|
| 157 |
+
learning_rate=2e-4,
|
| 158 |
+
fp16=args.fp16,
|
| 159 |
+
logging_steps=logging_steps,
|
| 160 |
+
save_steps=save_steps,
|
| 161 |
+
save_total_limit=2,
|
| 162 |
+
remove_unused_columns=False,
|
| 163 |
+
push_to_hub=False,
|
| 164 |
+
report_to=None, # Disable wandb/tensorboard
|
| 165 |
+
dataloader_pin_memory=False,
|
| 166 |
+
max_steps=1 if args.dry_run else None,
|
| 167 |
+
)
|
| 168 |
+
|
| 169 |
+
def main():
|
| 170 |
+
"""
|
| 171 |
+
Main function to execute the improved fine-tuning process.
|
| 172 |
+
"""
|
| 173 |
+
logger.info("Starting Improved AI Code Analyzer fine-tuning process")
|
| 174 |
+
|
| 175 |
+
parser = argparse.ArgumentParser(description="Fine-tune specialized code analysis models with QLoRA")
|
| 176 |
+
|
| 177 |
+
# Model selection with better defaults
|
| 178 |
+
parser.add_argument("--model", type=str,
|
| 179 |
+
default="Salesforce/codet5p-220m", # Better default for code analysis
|
| 180 |
+
help="Base model ID (HF Hub). Options: Salesforce/codet5p-220m, microsoft/CodeBERT, facebook/incoder-1B")
|
| 181 |
+
|
| 182 |
+
parser.add_argument("--subset", type=int, default=None, help="Use only the first N samples from the dataset")
|
| 183 |
+
parser.add_argument("--epochs", type=int, default=None, help="Number of training epochs")
|
| 184 |
+
parser.add_argument("--batch-size", type=int, default=None, help="Per-device train batch size")
|
| 185 |
+
parser.add_argument("--max-steps", type=int, default=None, help="Override maximum training steps")
|
| 186 |
+
parser.add_argument("--dry-run", action="store_true", help="Run a very short demo training")
|
| 187 |
+
parser.add_argument("--no-quant", action="store_true", help="Disable 4-bit quantization")
|
| 188 |
+
parser.add_argument("--fp16", action="store_true", default=True, help="Use FP16 precision")
|
| 189 |
+
|
| 190 |
+
args = parser.parse_args()
|
| 191 |
+
|
| 192 |
+
# Check if CUDA is available
|
| 193 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 194 |
+
logger.info(f"Using device: {device}")
|
| 195 |
+
if device == "cpu":
|
| 196 |
+
logger.warning("CUDA not available. Training will be slow on CPU.")
|
| 197 |
+
|
| 198 |
+
# Step 1: Load the dataset
|
| 199 |
+
logger.info("Step 1: Loading dataset...")
|
| 200 |
+
dataset = load_dataset("analyst_dataset.jsonl")
|
| 201 |
+
if args.subset is not None and args.subset > 0:
|
| 202 |
+
logger.info(f"Using only the first {args.subset} samples for this run")
|
| 203 |
+
dataset = dataset.select(range(min(args.subset, len(dataset))))
|
| 204 |
+
|
| 205 |
+
# Step 2: Load the base model and tokenizer
|
| 206 |
+
logger.info("Step 2: Loading model and tokenizer...")
|
| 207 |
+
model_name = args.model
|
| 208 |
+
logger.info(f"Loading model: {model_name}")
|
| 209 |
+
|
| 210 |
+
# Get appropriate model class
|
| 211 |
+
model_class = get_model_class(model_name)
|
| 212 |
+
|
| 213 |
+
# Load tokenizer
|
| 214 |
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 215 |
+
|
| 216 |
+
# Add padding token if not present
|
| 217 |
+
if tokenizer.pad_token is None:
|
| 218 |
+
tokenizer.pad_token = tokenizer.eos_token
|
| 219 |
+
|
| 220 |
+
# Load model with quantization if enabled
|
| 221 |
+
if args.no_quant:
|
| 222 |
+
logger.info("Loading model without quantization")
|
| 223 |
+
model = model_class.from_pretrained(model_name)
|
| 224 |
+
else:
|
| 225 |
+
logger.info("Loading model with 4-bit quantization")
|
| 226 |
+
quantization_config = create_quantization_config()
|
| 227 |
+
model = model_class.from_pretrained(
|
| 228 |
+
model_name,
|
| 229 |
+
quantization_config=quantization_config,
|
| 230 |
+
device_map="auto"
|
| 231 |
+
)
|
| 232 |
+
|
| 233 |
+
# Step 3: Create LoRA configuration
|
| 234 |
+
logger.info("Step 3: Setting up LoRA configuration...")
|
| 235 |
+
lora_config = create_lora_config(model_name)
|
| 236 |
+
|
| 237 |
+
# Step 4: Apply LoRA to the model
|
| 238 |
+
logger.info("Step 4: Applying LoRA to model...")
|
| 239 |
+
model = get_peft_model(model, lora_config)
|
| 240 |
+
|
| 241 |
+
# Step 5: Print trainable parameters
|
| 242 |
+
model.print_trainable_parameters()
|
| 243 |
+
|
| 244 |
+
# Step 6: Create training arguments
|
| 245 |
+
logger.info("Step 6: Setting up training arguments...")
|
| 246 |
+
training_args = create_training_arguments(args)
|
| 247 |
+
|
| 248 |
+
# Step 7: Create trainer
|
| 249 |
+
logger.info("Step 7: Creating trainer...")
|
| 250 |
+
trainer = SFTTrainer(
|
| 251 |
+
model=model,
|
| 252 |
+
args=training_args,
|
| 253 |
+
train_dataset=dataset,
|
| 254 |
+
tokenizer=tokenizer,
|
| 255 |
+
dataset_text_field="text",
|
| 256 |
+
max_seq_length=2048,
|
| 257 |
+
packing=False,
|
| 258 |
+
)
|
| 259 |
+
|
| 260 |
+
# Step 8: Start training
|
| 261 |
+
logger.info("Step 8: Starting training...")
|
| 262 |
+
logger.info(f"Training with {len(dataset)} samples")
|
| 263 |
+
logger.info(f"Model: {model_name}")
|
| 264 |
+
logger.info(f"Device: {device}")
|
| 265 |
+
|
| 266 |
+
trainer.train()
|
| 267 |
+
|
| 268 |
+
# Step 9: Save the model
|
| 269 |
+
logger.info("Step 9: Saving model...")
|
| 270 |
+
trainer.save_model()
|
| 271 |
+
tokenizer.save_pretrained(training_args.output_dir)
|
| 272 |
+
|
| 273 |
+
logger.info("Training completed successfully!")
|
| 274 |
+
logger.info(f"Model saved to: {training_args.output_dir}")
|
| 275 |
+
|
| 276 |
+
if __name__ == "__main__":
|
| 277 |
+
main()
|
inference_demo.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
import os
|
| 3 |
+
import torch
|
| 4 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 5 |
+
from peft import PeftModel
|
| 6 |
+
|
| 7 |
+
# Settings
|
| 8 |
+
BASE_MODEL = os.environ.get("BASE_MODEL", "gpt2")
|
| 9 |
+
ADAPTER_DIR = os.environ.get("ADAPTER_DIR", "./fine-tuned-analyst/lora_adapters")
|
| 10 |
+
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 11 |
+
|
| 12 |
+
def load_model_and_tokenizer():
|
| 13 |
+
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL)
|
| 14 |
+
if tokenizer.pad_token is None:
|
| 15 |
+
tokenizer.pad_token = tokenizer.eos_token
|
| 16 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 17 |
+
BASE_MODEL,
|
| 18 |
+
torch_dtype=torch.float32 if DEVICE == "cpu" else torch.float16,
|
| 19 |
+
device_map="cpu" if DEVICE == "cpu" else "auto",
|
| 20 |
+
trust_remote_code=True,
|
| 21 |
+
low_cpu_mem_usage=True,
|
| 22 |
+
)
|
| 23 |
+
model = PeftModel.from_pretrained(model, ADAPTER_DIR)
|
| 24 |
+
model.to(DEVICE)
|
| 25 |
+
model.eval()
|
| 26 |
+
return model, tokenizer
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def generate(prompt: str, max_new_tokens: int = 256) -> str:
|
| 30 |
+
model, tokenizer = load_model_and_tokenizer()
|
| 31 |
+
inputs = tokenizer(prompt, return_tensors="pt").to(DEVICE)
|
| 32 |
+
with torch.no_grad():
|
| 33 |
+
out = model.generate(
|
| 34 |
+
**inputs,
|
| 35 |
+
max_new_tokens=max_new_tokens,
|
| 36 |
+
do_sample=True,
|
| 37 |
+
top_p=0.9,
|
| 38 |
+
temperature=0.7,
|
| 39 |
+
eos_token_id=tokenizer.eos_token_id,
|
| 40 |
+
pad_token_id=tokenizer.pad_token_id,
|
| 41 |
+
)
|
| 42 |
+
text = tokenizer.decode(out[0], skip_special_tokens=True)
|
| 43 |
+
return text
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
if __name__ == "__main__":
|
| 47 |
+
# A tiny prompt using the same schema
|
| 48 |
+
code = """def add_item(item, items=[]):\n items.append(item)\n return items\n"""
|
| 49 |
+
inst = (
|
| 50 |
+
"<s>[INST] Analyze this code for bugs, performance, and security issues. "
|
| 51 |
+
"Give a quality score from 1-100 and provide a detailed analysis. \n\nCode:\n```" + code + "``` [/INST]"
|
| 52 |
+
)
|
| 53 |
+
print("Device:", DEVICE)
|
| 54 |
+
print("Base model:", BASE_MODEL)
|
| 55 |
+
print("Adapters:", ADAPTER_DIR)
|
| 56 |
+
print("\n--- Generated Output ---\n")
|
| 57 |
+
print(generate(inst, max_new_tokens=200))
|
launch.py
DELETED
|
@@ -1,111 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
"""
|
| 3 |
-
Launch script for LLM Code Analyzer
|
| 4 |
-
Checks system requirements and starts the Streamlit app
|
| 5 |
-
"""
|
| 6 |
-
|
| 7 |
-
import sys
|
| 8 |
-
import os
|
| 9 |
-
import subprocess
|
| 10 |
-
from pathlib import Path
|
| 11 |
-
|
| 12 |
-
def check_requirements():
|
| 13 |
-
"""Check if all requirements are met."""
|
| 14 |
-
print("🔍 Checking system requirements...")
|
| 15 |
-
|
| 16 |
-
# Check Python version
|
| 17 |
-
if sys.version_info < (3, 11):
|
| 18 |
-
print(f"❌ Python 3.11+ required, found {sys.version}")
|
| 19 |
-
return False
|
| 20 |
-
print(f"✅ Python {sys.version.split()[0]}")
|
| 21 |
-
|
| 22 |
-
# Check if we're in the right directory
|
| 23 |
-
if not Path("app.py").exists():
|
| 24 |
-
print("❌ app.py not found. Please run from project root directory.")
|
| 25 |
-
return False
|
| 26 |
-
print("✅ Project structure verified")
|
| 27 |
-
|
| 28 |
-
# Check if analyzer module can be imported
|
| 29 |
-
try:
|
| 30 |
-
from analyzer import CodeAnalyzer
|
| 31 |
-
analyzer = CodeAnalyzer()
|
| 32 |
-
models = analyzer.available_models
|
| 33 |
-
print(f"✅ Analyzer module loaded successfully")
|
| 34 |
-
print(f"📊 Available models: {len(models)}")
|
| 35 |
-
|
| 36 |
-
if not models:
|
| 37 |
-
print("⚠️ No API keys configured in .env file")
|
| 38 |
-
print(" Add at least one API key to use the analyzer")
|
| 39 |
-
else:
|
| 40 |
-
for key, name in models.items():
|
| 41 |
-
print(f" • {name}")
|
| 42 |
-
|
| 43 |
-
except Exception as e:
|
| 44 |
-
print(f"❌ Failed to load analyzer: {e}")
|
| 45 |
-
return False
|
| 46 |
-
|
| 47 |
-
# Check Streamlit
|
| 48 |
-
try:
|
| 49 |
-
import streamlit
|
| 50 |
-
print(f"✅ Streamlit {streamlit.__version__}")
|
| 51 |
-
except ImportError:
|
| 52 |
-
print("❌ Streamlit not installed")
|
| 53 |
-
return False
|
| 54 |
-
|
| 55 |
-
return True
|
| 56 |
-
|
| 57 |
-
def launch_app():
|
| 58 |
-
"""Launch the Streamlit application."""
|
| 59 |
-
print("\n🚀 Starting LLM Code Analyzer...")
|
| 60 |
-
print("=" * 50)
|
| 61 |
-
|
| 62 |
-
try:
|
| 63 |
-
# Start Streamlit
|
| 64 |
-
cmd = [
|
| 65 |
-
sys.executable, "-m", "streamlit", "run", "app.py",
|
| 66 |
-
"--server.headless", "true",
|
| 67 |
-
"--server.port", "8501",
|
| 68 |
-
"--server.address", "0.0.0.0"
|
| 69 |
-
]
|
| 70 |
-
|
| 71 |
-
print("📱 Application will be available at:")
|
| 72 |
-
print(" • Local: http://localhost:8501")
|
| 73 |
-
print(" • Network: http://0.0.0.0:8501")
|
| 74 |
-
print("\n💡 Press Ctrl+C to stop the application")
|
| 75 |
-
print("=" * 50)
|
| 76 |
-
|
| 77 |
-
subprocess.run(cmd, check=True)
|
| 78 |
-
|
| 79 |
-
except KeyboardInterrupt:
|
| 80 |
-
print("\n👋 Application stopped by user")
|
| 81 |
-
except subprocess.CalledProcessError as e:
|
| 82 |
-
print(f"❌ Failed to start application: {e}")
|
| 83 |
-
return False
|
| 84 |
-
except Exception as e:
|
| 85 |
-
print(f"❌ Unexpected error: {e}")
|
| 86 |
-
return False
|
| 87 |
-
|
| 88 |
-
return True
|
| 89 |
-
|
| 90 |
-
def main():
|
| 91 |
-
"""Main entry point."""
|
| 92 |
-
print("🔍 LLM Code Analyzer - Launcher")
|
| 93 |
-
print("=" * 40)
|
| 94 |
-
|
| 95 |
-
# Check requirements first
|
| 96 |
-
if not check_requirements():
|
| 97 |
-
print("\n❌ Requirements check failed")
|
| 98 |
-
print("\nTo fix issues:")
|
| 99 |
-
print("1. Ensure Python 3.11+ is installed")
|
| 100 |
-
print("2. Run: pip install -r requirements.txt")
|
| 101 |
-
print("3. Configure API keys in .env file")
|
| 102 |
-
sys.exit(1)
|
| 103 |
-
|
| 104 |
-
print("\n✅ All requirements satisfied!")
|
| 105 |
-
|
| 106 |
-
# Launch the app
|
| 107 |
-
if not launch_app():
|
| 108 |
-
sys.exit(1)
|
| 109 |
-
|
| 110 |
-
if __name__ == "__main__":
|
| 111 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
launch_matrix.py
DELETED
|
@@ -1,144 +0,0 @@
|
|
| 1 |
-
#!/usr/bin/env python3
|
| 2 |
-
"""
|
| 3 |
-
🟢 MATRIX CODE ANALYZER LAUNCHER 🟢
|
| 4 |
-
Enter the Matrix... if you dare.
|
| 5 |
-
"""
|
| 6 |
-
|
| 7 |
-
import sys
|
| 8 |
-
import os
|
| 9 |
-
import subprocess
|
| 10 |
-
from pathlib import Path
|
| 11 |
-
|
| 12 |
-
def matrix_banner():
|
| 13 |
-
"""Display Matrix-style banner."""
|
| 14 |
-
print("""
|
| 15 |
-
🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
|
| 16 |
-
|
| 17 |
-
███╗ ███╗ █████╗ ████████╗██████╗ ██╗██╗ ██╗
|
| 18 |
-
████╗ ████║██╔══██╗╚══██╔══╝██╔══██╗██║╚██╗██╔╝
|
| 19 |
-
██╔████╔██║███████║ ██║ ██████╔╝██║ ╚███╔╝
|
| 20 |
-
██║╚██╔╝██║██╔══██║ ██║ ██╔══██╗██║ ██╔██╗
|
| 21 |
-
██║ ╚═╝ ██║██║ ██║ ██║ ██║ ██║██║██╔╝ ██╗
|
| 22 |
-
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝
|
| 23 |
-
|
| 24 |
-
█████╗ ███╗ ██╗ █████╗ ██╗ ██╗ ██╗███████╗███████╗██████╗
|
| 25 |
-
██╔══██╗████╗ ██║██╔══██╗██║ ╚██╗ ██╔╝╚══███╔╝██╔════╝██╔══██╗
|
| 26 |
-
███████║██╔██╗ ██║███████║██║ ╚████╔╝ ███╔╝ █████╗ ██████╔╝
|
| 27 |
-
██╔══██║██║╚██╗██║██╔══██║██║ ╚██╔╝ ███╔╝ ██╔══╝ ██╔══██╗
|
| 28 |
-
██║ ██║██║ ╚████║██║ ██║███████╗██║ ███████╗███████╗██║ ██║
|
| 29 |
-
╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝╚═╝ ╚══════╝╚══════╝╚═╝ ╚═╝
|
| 30 |
-
|
| 31 |
-
🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢
|
| 32 |
-
""")
|
| 33 |
-
print("🟢 NEURAL NETWORK INITIALIZATION SEQUENCE STARTING...")
|
| 34 |
-
print("🟢 'There is no spoon... only code.'")
|
| 35 |
-
print("🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢")
|
| 36 |
-
|
| 37 |
-
def check_matrix_requirements():
|
| 38 |
-
"""Check if the Matrix is ready."""
|
| 39 |
-
print("\n🟢 SCANNING MATRIX REQUIREMENTS...")
|
| 40 |
-
|
| 41 |
-
# Check Python version
|
| 42 |
-
if sys.version_info < (3, 11):
|
| 43 |
-
print(f"❌ INCOMPATIBLE_PYTHON_VERSION: {sys.version}")
|
| 44 |
-
print("🟢 UPGRADE_TO_PYTHON_3.11+_REQUIRED")
|
| 45 |
-
return False
|
| 46 |
-
print(f"✅ PYTHON_VERSION: {sys.version.split()[0]} [COMPATIBLE]")
|
| 47 |
-
|
| 48 |
-
# Check if we're in the right dimension
|
| 49 |
-
if not Path("matrix_app.py").exists():
|
| 50 |
-
print("❌ MATRIX_APP_NOT_FOUND")
|
| 51 |
-
print("🟢 ENSURE_YOU_ARE_IN_THE_CORRECT_DIRECTORY")
|
| 52 |
-
return False
|
| 53 |
-
print("✅ MATRIX_APPLICATION: LOCATED")
|
| 54 |
-
|
| 55 |
-
# Check if analyzer module is accessible
|
| 56 |
-
try:
|
| 57 |
-
from analyzer import CodeAnalyzer
|
| 58 |
-
analyzer = CodeAnalyzer()
|
| 59 |
-
models = analyzer.available_models
|
| 60 |
-
print(f"✅ NEURAL_NETWORKS: ONLINE")
|
| 61 |
-
print(f"🟢 AVAILABLE_AI_MODELS: {len(models)}")
|
| 62 |
-
|
| 63 |
-
if not models:
|
| 64 |
-
print("⚠️ NO_API_KEYS_DETECTED")
|
| 65 |
-
print("🟢 CONFIGURE_NEURAL_NETWORK_ACCESS_CODES")
|
| 66 |
-
print("🟢 REQUIRED: OPENAI • ANTHROPIC • GEMINI • DEEPSEEK")
|
| 67 |
-
else:
|
| 68 |
-
for key, name in models.items():
|
| 69 |
-
print(f" 🤖 {name} [READY]")
|
| 70 |
-
|
| 71 |
-
except Exception as e:
|
| 72 |
-
print(f"❌ NEURAL_NETWORK_ERROR: {e}")
|
| 73 |
-
return False
|
| 74 |
-
|
| 75 |
-
# Check Streamlit
|
| 76 |
-
try:
|
| 77 |
-
import streamlit
|
| 78 |
-
print(f"✅ MATRIX_INTERFACE: v{streamlit.__version__} [OPERATIONAL]")
|
| 79 |
-
except ImportError:
|
| 80 |
-
print("❌ MATRIX_INTERFACE_NOT_FOUND")
|
| 81 |
-
print("🟢 RUN: pip install streamlit")
|
| 82 |
-
return False
|
| 83 |
-
|
| 84 |
-
return True
|
| 85 |
-
|
| 86 |
-
def enter_matrix():
|
| 87 |
-
"""Enter the Matrix."""
|
| 88 |
-
print("\n🟢 INITIATING_MATRIX_SEQUENCE...")
|
| 89 |
-
print("🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢")
|
| 90 |
-
|
| 91 |
-
try:
|
| 92 |
-
# Start the Matrix interface
|
| 93 |
-
cmd = [
|
| 94 |
-
sys.executable, "-m", "streamlit", "run", "matrix_app.py",
|
| 95 |
-
"--server.headless", "true",
|
| 96 |
-
"--server.port", "8503",
|
| 97 |
-
"--server.address", "0.0.0.0"
|
| 98 |
-
]
|
| 99 |
-
|
| 100 |
-
print("🟢 MATRIX_PORTAL_COORDINATES:")
|
| 101 |
-
print(" 🌐 LOCAL_ACCESS: http://localhost:8503")
|
| 102 |
-
print(" 🌐 NETWORK_ACCESS: http://0.0.0.0:8503")
|
| 103 |
-
print("\n🟢 MATRIX_ACTIVATED...")
|
| 104 |
-
print("🟢 'Welcome to the real world, Neo.'")
|
| 105 |
-
print("🟢 [Press Ctrl+C to exit the Matrix]")
|
| 106 |
-
print("🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢")
|
| 107 |
-
|
| 108 |
-
subprocess.run(cmd, check=True)
|
| 109 |
-
|
| 110 |
-
except KeyboardInterrupt:
|
| 111 |
-
print("\n🟢 MATRIX_SESSION_TERMINATED")
|
| 112 |
-
print("🟢 'Until we meet again in the Matrix...'")
|
| 113 |
-
except subprocess.CalledProcessError as e:
|
| 114 |
-
print(f"❌ MATRIX_INITIALIZATION_FAILED: {e}")
|
| 115 |
-
return False
|
| 116 |
-
except Exception as e:
|
| 117 |
-
print(f"❌ UNEXPECTED_MATRIX_ERROR: {e}")
|
| 118 |
-
return False
|
| 119 |
-
|
| 120 |
-
return True
|
| 121 |
-
|
| 122 |
-
def main():
|
| 123 |
-
"""Main entry point to the Matrix."""
|
| 124 |
-
matrix_banner()
|
| 125 |
-
|
| 126 |
-
# Check if the Matrix is ready
|
| 127 |
-
if not check_matrix_requirements():
|
| 128 |
-
print("\n❌ MATRIX_REQUIREMENTS_NOT_MET")
|
| 129 |
-
print("\n🟢 TROUBLESHOOTING_PROTOCOL:")
|
| 130 |
-
print("1. ENSURE_PYTHON_3.11+_INSTALLED")
|
| 131 |
-
print("2. RUN: pip install -r requirements.txt")
|
| 132 |
-
print("3. CONFIGURE_API_KEYS_IN_.ENV_FILE")
|
| 133 |
-
print("4. RETRY_MATRIX_INITIALIZATION")
|
| 134 |
-
sys.exit(1)
|
| 135 |
-
|
| 136 |
-
print("\n✅ ALL_MATRIX_SYSTEMS_OPERATIONAL")
|
| 137 |
-
print("🟢 READY_TO_ENTER_THE_MATRIX...")
|
| 138 |
-
|
| 139 |
-
# Enter the Matrix
|
| 140 |
-
if not enter_matrix():
|
| 141 |
-
sys.exit(1)
|
| 142 |
-
|
| 143 |
-
if __name__ == "__main__":
|
| 144 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
matrix_analyzer_optimized.py
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Optimized Matrix Code Analyzer with CodeT5+
|
| 4 |
+
|
| 5 |
+
This integrates the optimized CodeT5+ analyzer into your existing
|
| 6 |
+
Matrix-themed Streamlit application with speed optimizations.
|
| 7 |
+
|
| 8 |
+
Author: AI Code Analyzer Project
|
| 9 |
+
Date: 2025
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import streamlit as st
|
| 13 |
+
import time
|
| 14 |
+
import torch
|
| 15 |
+
from optimized_code_analyzer import OptimizedCodeAnalyzer
|
| 16 |
+
|
| 17 |
+
# Page configuration
|
| 18 |
+
st.set_page_config(
|
| 19 |
+
page_title="AI Code Analyzer - Optimized",
|
| 20 |
+
page_icon="🤖",
|
| 21 |
+
layout="wide",
|
| 22 |
+
initial_sidebar_state="expanded"
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
# Custom CSS for Matrix theme
|
| 26 |
+
st.markdown("""
|
| 27 |
+
<style>
|
| 28 |
+
.main {
|
| 29 |
+
background-color: #0a0a0a;
|
| 30 |
+
color: #00ff00;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
.stApp {
|
| 34 |
+
background-color: #0a0a0a;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
.matrix-header {
|
| 38 |
+
background: linear-gradient(90deg, #00ff00, #008800);
|
| 39 |
+
color: #000000;
|
| 40 |
+
padding: 20px;
|
| 41 |
+
border-radius: 10px;
|
| 42 |
+
text-align: center;
|
| 43 |
+
margin-bottom: 30px;
|
| 44 |
+
font-family: 'Courier New', monospace;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
.analysis-box {
|
| 48 |
+
background-color: #001100;
|
| 49 |
+
border: 2px solid #00ff00;
|
| 50 |
+
border-radius: 10px;
|
| 51 |
+
padding: 20px;
|
| 52 |
+
margin: 10px 0;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
.speed-indicator {
|
| 56 |
+
background-color: #002200;
|
| 57 |
+
border: 1px solid #00ff00;
|
| 58 |
+
border-radius: 5px;
|
| 59 |
+
padding: 10px;
|
| 60 |
+
margin: 10px 0;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
.cache-info {
|
| 64 |
+
background-color: #000800;
|
| 65 |
+
border: 1px solid #008800;
|
| 66 |
+
border-radius: 5px;
|
| 67 |
+
padding: 10px;
|
| 68 |
+
margin: 10px 0;
|
| 69 |
+
font-size: 12px;
|
| 70 |
+
}
|
| 71 |
+
</style>
|
| 72 |
+
""", unsafe_allow_html=True)
|
| 73 |
+
|
| 74 |
+
@st.cache_resource
|
| 75 |
+
def load_analyzer():
|
| 76 |
+
"""
|
| 77 |
+
Load the optimized analyzer (cached for performance).
|
| 78 |
+
"""
|
| 79 |
+
return OptimizedCodeAnalyzer()
|
| 80 |
+
|
| 81 |
+
def main():
|
| 82 |
+
"""
|
| 83 |
+
Main Streamlit application.
|
| 84 |
+
"""
|
| 85 |
+
# Header
|
| 86 |
+
st.markdown("""
|
| 87 |
+
<div class="matrix-header">
|
| 88 |
+
<h1>🤖 AI Code Analyzer - Optimized</h1>
|
| 89 |
+
<p>Powered by CodeT5+ with Speed Optimizations</p>
|
| 90 |
+
</div>
|
| 91 |
+
""", unsafe_allow_html=True)
|
| 92 |
+
|
| 93 |
+
# Load analyzer
|
| 94 |
+
with st.spinner("🚀 Loading optimized CodeT5+ model..."):
|
| 95 |
+
analyzer = load_analyzer()
|
| 96 |
+
|
| 97 |
+
# Sidebar
|
| 98 |
+
st.sidebar.markdown("## ⚙️ Analysis Options")
|
| 99 |
+
|
| 100 |
+
analysis_mode = st.sidebar.selectbox(
|
| 101 |
+
"Analysis Mode",
|
| 102 |
+
["Streaming (Interactive)", "Fast (Batch)"],
|
| 103 |
+
help="Streaming shows progress, Fast is optimized for speed"
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
show_progress = st.sidebar.checkbox(
|
| 107 |
+
"Show Progress Indicators",
|
| 108 |
+
value=True,
|
| 109 |
+
help="Display progress bars and timing information"
|
| 110 |
+
)
|
| 111 |
+
|
| 112 |
+
# Main content
|
| 113 |
+
col1, col2 = st.columns([1, 1])
|
| 114 |
+
|
| 115 |
+
with col1:
|
| 116 |
+
st.markdown("## 📝 Code Input")
|
| 117 |
+
|
| 118 |
+
# Code input
|
| 119 |
+
code_input = st.text_area(
|
| 120 |
+
"Enter your code:",
|
| 121 |
+
height=300,
|
| 122 |
+
placeholder="def hello():\n print('Hello, World!')",
|
| 123 |
+
help="Paste your code here for analysis"
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
# Analysis button
|
| 127 |
+
analyze_button = st.button(
|
| 128 |
+
"🔍 Analyze Code",
|
| 129 |
+
type="primary",
|
| 130 |
+
use_container_width=True
|
| 131 |
+
)
|
| 132 |
+
|
| 133 |
+
with col2:
|
| 134 |
+
st.markdown("## 📊 Analysis Results")
|
| 135 |
+
|
| 136 |
+
if analyze_button and code_input.strip():
|
| 137 |
+
# Perform analysis
|
| 138 |
+
start_time = time.time()
|
| 139 |
+
|
| 140 |
+
if analysis_mode == "Streaming (Interactive)":
|
| 141 |
+
# Streaming analysis
|
| 142 |
+
st.markdown("### 🔄 Streaming Analysis")
|
| 143 |
+
|
| 144 |
+
# Create placeholder for streaming results
|
| 145 |
+
result_placeholder = st.empty()
|
| 146 |
+
progress_placeholder = st.empty()
|
| 147 |
+
|
| 148 |
+
# Show progress
|
| 149 |
+
if show_progress:
|
| 150 |
+
progress_bar = progress_placeholder.progress(0)
|
| 151 |
+
status_text = st.empty()
|
| 152 |
+
|
| 153 |
+
try:
|
| 154 |
+
# Stream analysis
|
| 155 |
+
analysis_text = ""
|
| 156 |
+
for partial_result in analyzer.analyze_code_streaming(code_input, show_progress):
|
| 157 |
+
analysis_text = partial_result
|
| 158 |
+
|
| 159 |
+
# Update progress
|
| 160 |
+
if show_progress:
|
| 161 |
+
progress_bar.progress(50)
|
| 162 |
+
status_text.text("🔍 Analyzing code...")
|
| 163 |
+
|
| 164 |
+
# Complete analysis
|
| 165 |
+
if show_progress:
|
| 166 |
+
progress_bar.progress(100)
|
| 167 |
+
status_text.text("✅ Analysis complete!")
|
| 168 |
+
|
| 169 |
+
# Display results
|
| 170 |
+
result_placeholder.markdown(f"""
|
| 171 |
+
<div class="analysis-box">
|
| 172 |
+
<h4>📄 Analysis Results:</h4>
|
| 173 |
+
<p>{analysis_text}</p>
|
| 174 |
+
</div>
|
| 175 |
+
""", unsafe_allow_html=True)
|
| 176 |
+
|
| 177 |
+
except Exception as e:
|
| 178 |
+
st.error(f"❌ Analysis failed: {str(e)}")
|
| 179 |
+
|
| 180 |
+
else:
|
| 181 |
+
# Fast analysis
|
| 182 |
+
st.markdown("### ⚡ Fast Analysis")
|
| 183 |
+
|
| 184 |
+
if show_progress:
|
| 185 |
+
progress_bar = st.progress(0)
|
| 186 |
+
status_text = st.empty()
|
| 187 |
+
progress_bar.progress(25)
|
| 188 |
+
status_text.text("🚀 Loading model...")
|
| 189 |
+
|
| 190 |
+
try:
|
| 191 |
+
# Perform fast analysis
|
| 192 |
+
result = analyzer.analyze_code_fast(code_input)
|
| 193 |
+
|
| 194 |
+
if show_progress:
|
| 195 |
+
progress_bar.progress(100)
|
| 196 |
+
status_text.text("✅ Analysis complete!")
|
| 197 |
+
|
| 198 |
+
# Display results
|
| 199 |
+
st.markdown(f"""
|
| 200 |
+
<div class="analysis-box">
|
| 201 |
+
<h4>📄 Analysis Results:</h4>
|
| 202 |
+
<p>{result['analysis']}</p>
|
| 203 |
+
</div>
|
| 204 |
+
""", unsafe_allow_html=True)
|
| 205 |
+
|
| 206 |
+
except Exception as e:
|
| 207 |
+
st.error(f"❌ Analysis failed: {str(e)}")
|
| 208 |
+
|
| 209 |
+
# Show performance metrics
|
| 210 |
+
total_time = time.time() - start_time
|
| 211 |
+
|
| 212 |
+
st.markdown(f"""
|
| 213 |
+
<div class="speed-indicator">
|
| 214 |
+
<h4>⚡ Performance Metrics:</h4>
|
| 215 |
+
<p><strong>Total Time:</strong> {total_time:.2f}s</p>
|
| 216 |
+
<p><strong>Analysis Mode:</strong> {analysis_mode}</p>
|
| 217 |
+
<p><strong>Model:</strong> CodeT5+ (Optimized)</p>
|
| 218 |
+
</div>
|
| 219 |
+
""", unsafe_allow_html=True)
|
| 220 |
+
|
| 221 |
+
elif analyze_button and not code_input.strip():
|
| 222 |
+
st.warning("⚠️ Please enter some code to analyze!")
|
| 223 |
+
|
| 224 |
+
else:
|
| 225 |
+
st.info("👆 Enter code and click 'Analyze Code' to get started!")
|
| 226 |
+
|
| 227 |
+
# Model information
|
| 228 |
+
st.markdown("## 📊 Model Information")
|
| 229 |
+
|
| 230 |
+
model_info = analyzer.get_model_info()
|
| 231 |
+
|
| 232 |
+
col1, col2, col3 = st.columns(3)
|
| 233 |
+
|
| 234 |
+
with col1:
|
| 235 |
+
st.metric("Model Parameters", f"{model_info['parameters']:,}")
|
| 236 |
+
|
| 237 |
+
with col2:
|
| 238 |
+
st.metric("Cache Size", f"{model_info['cache_size']} analyses")
|
| 239 |
+
|
| 240 |
+
with col3:
|
| 241 |
+
st.metric("Device", str(model_info['device']))
|
| 242 |
+
|
| 243 |
+
# Cache information
|
| 244 |
+
st.markdown("""
|
| 245 |
+
<div class="cache-info">
|
| 246 |
+
<h4>💾 Cache Information:</h4>
|
| 247 |
+
<p>• Cached analyses are reused for identical code</p>
|
| 248 |
+
<p>• Cache improves speed for repeated analyses</p>
|
| 249 |
+
<p>• Cache is automatically managed</p>
|
| 250 |
+
</div>
|
| 251 |
+
""", unsafe_allow_html=True)
|
| 252 |
+
|
| 253 |
+
# Footer
|
| 254 |
+
st.markdown("---")
|
| 255 |
+
st.markdown("""
|
| 256 |
+
<div style="text-align: center; color: #008800;">
|
| 257 |
+
<p>🚀 Optimized AI Code Analyzer | Powered by CodeT5+ | Matrix Theme</p>
|
| 258 |
+
</div>
|
| 259 |
+
""", unsafe_allow_html=True)
|
| 260 |
+
|
| 261 |
+
if __name__ == "__main__":
|
| 262 |
+
main()
|
matrix_app.py
DELETED
|
@@ -1,638 +0,0 @@
|
|
| 1 |
-
import streamlit as st
|
| 2 |
-
import os
|
| 3 |
-
import time
|
| 4 |
-
import random
|
| 5 |
-
import sys
|
| 6 |
-
from dotenv import load_dotenv
|
| 7 |
-
from analyzer import CodeAnalyzer
|
| 8 |
-
|
| 9 |
-
# Load environment variables
|
| 10 |
-
load_dotenv()
|
| 11 |
-
|
| 12 |
-
# Page config
|
| 13 |
-
st.set_page_config(
|
| 14 |
-
page_title="Matrix Code Analyzer",
|
| 15 |
-
page_icon="🟢",
|
| 16 |
-
layout="wide",
|
| 17 |
-
initial_sidebar_state="expanded"
|
| 18 |
-
)
|
| 19 |
-
|
| 20 |
-
# Matrix CSS - Cyberpunk Theme
|
| 21 |
-
st.markdown("""
|
| 22 |
-
<style>
|
| 23 |
-
@import url('https://fonts.googleapis.com/css2?family=Share+Tech+Mono:wght@400&display=swap');
|
| 24 |
-
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
|
| 25 |
-
|
| 26 |
-
/* Matrix Background */
|
| 27 |
-
.stApp {
|
| 28 |
-
background: linear-gradient(135deg, #0d1b0d 0%, #000000 50%, #0d1b0d 100%);
|
| 29 |
-
color: #00ff41;
|
| 30 |
-
font-family: 'Share Tech Mono', monospace;
|
| 31 |
-
}
|
| 32 |
-
|
| 33 |
-
/* Matrix Code Rain Animation */
|
| 34 |
-
.matrix-bg {
|
| 35 |
-
position: fixed;
|
| 36 |
-
top: 0;
|
| 37 |
-
left: 0;
|
| 38 |
-
width: 100%;
|
| 39 |
-
height: 100%;
|
| 40 |
-
overflow: hidden;
|
| 41 |
-
z-index: -1;
|
| 42 |
-
opacity: 0.1;
|
| 43 |
-
}
|
| 44 |
-
|
| 45 |
-
.matrix-char {
|
| 46 |
-
position: absolute;
|
| 47 |
-
color: #00ff41;
|
| 48 |
-
font-family: 'Share Tech Mono', monospace;
|
| 49 |
-
font-size: 14px;
|
| 50 |
-
animation: matrix-fall linear infinite;
|
| 51 |
-
}
|
| 52 |
-
|
| 53 |
-
@keyframes matrix-fall {
|
| 54 |
-
0% { transform: translateY(-100vh); opacity: 1; }
|
| 55 |
-
100% { transform: translateY(100vh); opacity: 0; }
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
/* Main Content Styling */
|
| 59 |
-
.main .block-container {
|
| 60 |
-
padding-top: 2rem;
|
| 61 |
-
background: rgba(0, 0, 0, 0.8);
|
| 62 |
-
border: 1px solid #00ff41;
|
| 63 |
-
border-radius: 10px;
|
| 64 |
-
box-shadow: 0 0 20px rgba(0, 255, 65, 0.3);
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
/* Title Styling */
|
| 68 |
-
h1 {
|
| 69 |
-
font-family: 'Orbitron', monospace !important;
|
| 70 |
-
color: #00ff41 !important;
|
| 71 |
-
text-align: center !important;
|
| 72 |
-
text-shadow: 0 0 10px #00ff41, 0 0 20px #00ff41, 0 0 30px #00ff41;
|
| 73 |
-
font-weight: 900 !important;
|
| 74 |
-
margin-bottom: 2rem !important;
|
| 75 |
-
animation: glow 2s ease-in-out infinite alternate;
|
| 76 |
-
}
|
| 77 |
-
|
| 78 |
-
@keyframes glow {
|
| 79 |
-
from { text-shadow: 0 0 5px #00ff41, 0 0 10px #00ff41, 0 0 15px #00ff41; }
|
| 80 |
-
to { text-shadow: 0 0 10px #00ff41, 0 0 20px #00ff41, 0 0 30px #00ff41; }
|
| 81 |
-
}
|
| 82 |
-
|
| 83 |
-
/* Sidebar Styling */
|
| 84 |
-
.css-1d391kg {
|
| 85 |
-
background: rgba(0, 0, 0, 0.9) !important;
|
| 86 |
-
border: 1px solid #00ff41 !important;
|
| 87 |
-
border-radius: 10px !important;
|
| 88 |
-
}
|
| 89 |
-
|
| 90 |
-
/* Buttons */
|
| 91 |
-
.stButton > button {
|
| 92 |
-
background: linear-gradient(45deg, #003300, #006600) !important;
|
| 93 |
-
color: #00ff41 !important;
|
| 94 |
-
border: 2px solid #00ff41 !important;
|
| 95 |
-
border-radius: 5px !important;
|
| 96 |
-
font-family: 'Orbitron', monospace !important;
|
| 97 |
-
font-weight: bold !important;
|
| 98 |
-
text-transform: uppercase !important;
|
| 99 |
-
transition: all 0.3s ease !important;
|
| 100 |
-
box-shadow: 0 0 10px rgba(0, 255, 65, 0.3) !important;
|
| 101 |
-
}
|
| 102 |
-
|
| 103 |
-
.stButton > button:hover {
|
| 104 |
-
background: linear-gradient(45deg, #006600, #00aa00) !important;
|
| 105 |
-
box-shadow: 0 0 20px rgba(0, 255, 65, 0.6) !important;
|
| 106 |
-
transform: translateY(-2px) !important;
|
| 107 |
-
}
|
| 108 |
-
|
| 109 |
-
/* Select boxes */
|
| 110 |
-
.stSelectbox > div > div {
|
| 111 |
-
background: rgba(0, 51, 0, 0.8) !important;
|
| 112 |
-
border: 1px solid #00ff41 !important;
|
| 113 |
-
color: #00ff41 !important;
|
| 114 |
-
}
|
| 115 |
-
|
| 116 |
-
/* Text areas */
|
| 117 |
-
.stTextArea > div > div > textarea {
|
| 118 |
-
background: rgba(0, 0, 0, 0.9) !important;
|
| 119 |
-
border: 1px solid #00ff41 !important;
|
| 120 |
-
color: #00ff41 !important;
|
| 121 |
-
font-family: 'Share Tech Mono', monospace !important;
|
| 122 |
-
}
|
| 123 |
-
|
| 124 |
-
/* Metrics */
|
| 125 |
-
.css-1xarl3l {
|
| 126 |
-
background: rgba(0, 51, 0, 0.3) !important;
|
| 127 |
-
border: 1px solid #00ff41 !important;
|
| 128 |
-
border-radius: 5px !important;
|
| 129 |
-
box-shadow: 0 0 10px rgba(0, 255, 65, 0.2) !important;
|
| 130 |
-
}
|
| 131 |
-
|
| 132 |
-
/* Success/Info/Warning messages */
|
| 133 |
-
.stSuccess {
|
| 134 |
-
background: rgba(0, 255, 65, 0.1) !important;
|
| 135 |
-
border: 1px solid #00ff41 !important;
|
| 136 |
-
color: #00ff41 !important;
|
| 137 |
-
}
|
| 138 |
-
|
| 139 |
-
.stInfo {
|
| 140 |
-
background: rgba(0, 255, 255, 0.1) !important;
|
| 141 |
-
border: 1px solid #00ffff !important;
|
| 142 |
-
color: #00ffff !important;
|
| 143 |
-
}
|
| 144 |
-
|
| 145 |
-
.stWarning {
|
| 146 |
-
background: rgba(255, 255, 0, 0.1) !important;
|
| 147 |
-
border: 1px solid #ffff00 !important;
|
| 148 |
-
color: #ffff00 !important;
|
| 149 |
-
}
|
| 150 |
-
|
| 151 |
-
.stError {
|
| 152 |
-
background: rgba(255, 0, 0, 0.1) !important;
|
| 153 |
-
border: 1px solid #ff0000 !important;
|
| 154 |
-
color: #ff0000 !important;
|
| 155 |
-
}
|
| 156 |
-
|
| 157 |
-
/* Code blocks */
|
| 158 |
-
.stCode {
|
| 159 |
-
background: rgba(0, 0, 0, 0.9) !important;
|
| 160 |
-
border: 1px solid #00ff41 !important;
|
| 161 |
-
color: #00ff41 !important;
|
| 162 |
-
}
|
| 163 |
-
|
| 164 |
-
/* Tabs */
|
| 165 |
-
.stTabs [data-baseweb="tab-list"] {
|
| 166 |
-
background: rgba(0, 0, 0, 0.8) !important;
|
| 167 |
-
border-bottom: 2px solid #00ff41 !important;
|
| 168 |
-
}
|
| 169 |
-
|
| 170 |
-
.stTabs [data-baseweb="tab"] {
|
| 171 |
-
background: rgba(0, 51, 0, 0.3) !important;
|
| 172 |
-
color: #00ff41 !important;
|
| 173 |
-
border: 1px solid #00ff41 !important;
|
| 174 |
-
font-family: 'Orbitron', monospace !important;
|
| 175 |
-
}
|
| 176 |
-
|
| 177 |
-
.stTabs [aria-selected="true"] {
|
| 178 |
-
background: rgba(0, 255, 65, 0.2) !important;
|
| 179 |
-
box-shadow: 0 0 10px rgba(0, 255, 65, 0.5) !important;
|
| 180 |
-
}
|
| 181 |
-
|
| 182 |
-
/* Matrix Terminal Effect */
|
| 183 |
-
.matrix-terminal {
|
| 184 |
-
background: rgba(0, 0, 0, 0.95) !important;
|
| 185 |
-
border: 2px solid #00ff41 !important;
|
| 186 |
-
border-radius: 10px !important;
|
| 187 |
-
padding: 20px !important;
|
| 188 |
-
font-family: 'Share Tech Mono', monospace !important;
|
| 189 |
-
color: #00ff41 !important;
|
| 190 |
-
box-shadow: 0 0 30px rgba(0, 255, 65, 0.4) !important;
|
| 191 |
-
position: relative !important;
|
| 192 |
-
}
|
| 193 |
-
|
| 194 |
-
.matrix-terminal::before {
|
| 195 |
-
content: "MATRIX_ANALYZER_v2.0 > ACTIVE" !important;
|
| 196 |
-
position: absolute !important;
|
| 197 |
-
top: -15px !important;
|
| 198 |
-
left: 20px !important;
|
| 199 |
-
background: #000000 !important;
|
| 200 |
-
padding: 0 10px !important;
|
| 201 |
-
color: #00ff41 !important;
|
| 202 |
-
font-size: 12px !important;
|
| 203 |
-
font-weight: bold !important;
|
| 204 |
-
}
|
| 205 |
-
|
| 206 |
-
/* Scrollbar */
|
| 207 |
-
::-webkit-scrollbar {
|
| 208 |
-
width: 8px;
|
| 209 |
-
}
|
| 210 |
-
|
| 211 |
-
::-webkit-scrollbar-track {
|
| 212 |
-
background: #000000;
|
| 213 |
-
}
|
| 214 |
-
|
| 215 |
-
::-webkit-scrollbar-thumb {
|
| 216 |
-
background: #00ff41;
|
| 217 |
-
border-radius: 4px;
|
| 218 |
-
}
|
| 219 |
-
|
| 220 |
-
::-webkit-scrollbar-thumb:hover {
|
| 221 |
-
background: #00aa00;
|
| 222 |
-
}
|
| 223 |
-
|
| 224 |
-
/* Loading spinner */
|
| 225 |
-
.stSpinner > div {
|
| 226 |
-
border-color: #00ff41 transparent #00ff41 transparent !important;
|
| 227 |
-
}
|
| 228 |
-
|
| 229 |
-
/* Expander */
|
| 230 |
-
.streamlit-expanderHeader {
|
| 231 |
-
background: rgba(0, 51, 0, 0.3) !important;
|
| 232 |
-
border: 1px solid #00ff41 !important;
|
| 233 |
-
color: #00ff41 !important;
|
| 234 |
-
}
|
| 235 |
-
</style>
|
| 236 |
-
|
| 237 |
-
<div class="matrix-bg" id="matrix-bg"></div>
|
| 238 |
-
|
| 239 |
-
<script>
|
| 240 |
-
function createMatrixRain() {
|
| 241 |
-
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()_+-=[]{}|;:,.<>?";
|
| 242 |
-
const container = document.getElementById('matrix-bg');
|
| 243 |
-
|
| 244 |
-
for (let i = 0; i < 50; i++) {
|
| 245 |
-
const char = document.createElement('div');
|
| 246 |
-
char.className = 'matrix-char';
|
| 247 |
-
char.textContent = chars[Math.floor(Math.random() * chars.length)];
|
| 248 |
-
char.style.left = Math.random() * 100 + '%';
|
| 249 |
-
char.style.animationDuration = (Math.random() * 3 + 2) + 's';
|
| 250 |
-
char.style.animationDelay = Math.random() * 2 + 's';
|
| 251 |
-
container.appendChild(char);
|
| 252 |
-
}
|
| 253 |
-
}
|
| 254 |
-
|
| 255 |
-
// Create matrix rain effect
|
| 256 |
-
setTimeout(createMatrixRain, 100);
|
| 257 |
-
</script>
|
| 258 |
-
""", unsafe_allow_html=True)
|
| 259 |
-
|
| 260 |
-
# Initialize analyzer
|
| 261 |
-
@st.cache_resource
|
| 262 |
-
def get_analyzer():
|
| 263 |
-
return CodeAnalyzer()
|
| 264 |
-
|
| 265 |
-
analyzer = get_analyzer()
|
| 266 |
-
|
| 267 |
-
def display_matrix_analysis_result(result: dict, model_name: str):
|
| 268 |
-
"""Display analysis result in Matrix terminal style."""
|
| 269 |
-
if 'error' in result:
|
| 270 |
-
st.error(f"🚨 SYSTEM ERROR: {result['error']}")
|
| 271 |
-
return
|
| 272 |
-
|
| 273 |
-
# Quality score with Matrix styling
|
| 274 |
-
score = result['quality_score']
|
| 275 |
-
if score >= 80:
|
| 276 |
-
score_color = "#00ff41"
|
| 277 |
-
status = "OPTIMAL"
|
| 278 |
-
elif score >= 60:
|
| 279 |
-
score_color = "#ffff00"
|
| 280 |
-
status = "ACCEPTABLE"
|
| 281 |
-
else:
|
| 282 |
-
score_color = "#ff0000"
|
| 283 |
-
status = "CRITICAL"
|
| 284 |
-
|
| 285 |
-
st.markdown(f"""
|
| 286 |
-
<div class="matrix-terminal">
|
| 287 |
-
<h3 style="color: {score_color}; font-family: 'Orbitron', monospace; text-align: center;">
|
| 288 |
-
[{model_name}] ANALYSIS COMPLETE
|
| 289 |
-
</h3>
|
| 290 |
-
<div style="display: flex; justify-content: space-between; margin: 20px 0;">
|
| 291 |
-
<div>
|
| 292 |
-
<span style="font-size: 2.5rem; color: {score_color}; font-weight: bold;">
|
| 293 |
-
{score}/100
|
| 294 |
-
</span>
|
| 295 |
-
<p style="margin: 0; color: {score_color}; font-weight: bold;">
|
| 296 |
-
STATUS: {status}
|
| 297 |
-
</p>
|
| 298 |
-
</div>
|
| 299 |
-
<div style="text-align: right; color: #00ff41;">
|
| 300 |
-
<p style="margin: 0;"><strong>LANGUAGE:</strong> {result['language'].upper()}</p>
|
| 301 |
-
<p style="margin: 0;"><strong>SCAN_TIME:</strong> {result['execution_time']}s</p>
|
| 302 |
-
<p style="margin: 0;"><strong>CODE_LINES:</strong> {result['line_count']}</p>
|
| 303 |
-
</div>
|
| 304 |
-
</div>
|
| 305 |
-
</div>
|
| 306 |
-
""", unsafe_allow_html=True)
|
| 307 |
-
|
| 308 |
-
# Summary in terminal style
|
| 309 |
-
if result.get('summary'):
|
| 310 |
-
st.markdown("#### 📋 SYSTEM ANALYSIS")
|
| 311 |
-
st.markdown(f"""
|
| 312 |
-
<div style="background: rgba(0,0,0,0.8); border: 1px solid #00ff41; padding: 15px; border-radius: 5px; font-family: 'Share Tech Mono', monospace;">
|
| 313 |
-
> {result['summary']}
|
| 314 |
-
</div>
|
| 315 |
-
""", unsafe_allow_html=True)
|
| 316 |
-
|
| 317 |
-
# Create columns for different sections
|
| 318 |
-
col1, col2 = st.columns(2)
|
| 319 |
-
|
| 320 |
-
with col1:
|
| 321 |
-
# Strengths
|
| 322 |
-
if result.get('strengths'):
|
| 323 |
-
st.markdown("#### ✅ SYSTEM STRENGTHS")
|
| 324 |
-
for strength in result['strengths']:
|
| 325 |
-
st.success(f"[+] {strength}")
|
| 326 |
-
|
| 327 |
-
# Suggestions
|
| 328 |
-
if result.get('suggestions'):
|
| 329 |
-
st.markdown("#### 💡 ENHANCEMENT_PROTOCOLS")
|
| 330 |
-
for suggestion in result['suggestions']:
|
| 331 |
-
st.info(f"[*] {suggestion}")
|
| 332 |
-
|
| 333 |
-
with col2:
|
| 334 |
-
# Issues
|
| 335 |
-
if result.get('issues'):
|
| 336 |
-
st.markdown("#### ⚠️ SYSTEM_VULNERABILITIES")
|
| 337 |
-
for issue in result['issues']:
|
| 338 |
-
st.warning(f"[!] {issue}")
|
| 339 |
-
|
| 340 |
-
# Security concerns
|
| 341 |
-
if result.get('security_concerns'):
|
| 342 |
-
st.markdown("#### 🔒 SECURITY_BREACH_DETECTED")
|
| 343 |
-
for concern in result['security_concerns']:
|
| 344 |
-
st.error(f"[ALERT] {concern}")
|
| 345 |
-
|
| 346 |
-
# Performance notes
|
| 347 |
-
if result.get('performance_notes'):
|
| 348 |
-
st.markdown("#### ⚡ PERFORMANCE_OPTIMIZATION")
|
| 349 |
-
for note in result['performance_notes']:
|
| 350 |
-
st.info(f"[PERF] {note}")
|
| 351 |
-
|
| 352 |
-
# Expandable raw response
|
| 353 |
-
with st.expander("VIEW RAW_DATA_STREAM"):
|
| 354 |
-
st.code(result.get('raw_response', 'NO_DATA_AVAILABLE'), language='text')
|
| 355 |
-
|
| 356 |
-
# Header with Matrix effect
|
| 357 |
-
st.markdown("""
|
| 358 |
-
<h1 style="text-align: center;">
|
| 359 |
-
🟢 MATRIX CODE ANALYZER 🟢
|
| 360 |
-
</h1>
|
| 361 |
-
<p style="text-align: center; color: #00ff41; font-family: 'Share Tech Mono', monospace; font-size: 18px;">
|
| 362 |
-
[NEURAL_NETWORK_ACTIVATED] • [MULTI_AI_ANALYSIS_ONLINE] • [SECURITY_LEVEL_9]
|
| 363 |
-
</p>
|
| 364 |
-
""", unsafe_allow_html=True)
|
| 365 |
-
|
| 366 |
-
# Sidebar - The Matrix Control Panel
|
| 367 |
-
with st.sidebar:
|
| 368 |
-
st.markdown("### 🟢 CONTROL_PANEL")
|
| 369 |
-
|
| 370 |
-
# Model status
|
| 371 |
-
st.markdown("#### AVAILABLE_NEURAL_NETWORKS")
|
| 372 |
-
available_models = analyzer.available_models
|
| 373 |
-
|
| 374 |
-
if not available_models:
|
| 375 |
-
st.error("❌ NO_NETWORKS_DETECTED")
|
| 376 |
-
st.info("CONFIGURE_API_KEYS_IN_ENV_FILE")
|
| 377 |
-
st.stop()
|
| 378 |
-
|
| 379 |
-
# Display available models with Matrix styling
|
| 380 |
-
for model, display_name in available_models.items():
|
| 381 |
-
st.markdown(f"""
|
| 382 |
-
<div style="background: rgba(0, 255, 65, 0.1); border: 1px solid #00ff41; padding: 5px; margin: 5px 0; border-radius: 3px;">
|
| 383 |
-
🟢 <strong>{display_name}</strong> [ONLINE]
|
| 384 |
-
</div>
|
| 385 |
-
""", unsafe_allow_html=True)
|
| 386 |
-
|
| 387 |
-
st.markdown("---")
|
| 388 |
-
|
| 389 |
-
# Analysis options
|
| 390 |
-
st.markdown("#### ANALYSIS_PARAMETERS")
|
| 391 |
-
|
| 392 |
-
# Model selector with Matrix styling
|
| 393 |
-
selected_model = st.selectbox(
|
| 394 |
-
"SELECT_NEURAL_NETWORK",
|
| 395 |
-
options=list(available_models.keys()),
|
| 396 |
-
format_func=lambda x: f"🤖 {available_models[x]}"
|
| 397 |
-
)
|
| 398 |
-
|
| 399 |
-
# Multi-model analysis toggle
|
| 400 |
-
analyze_all = st.checkbox("🔄 MULTI_NETWORK_SCAN", value=False)
|
| 401 |
-
|
| 402 |
-
# Analysis mode selection
|
| 403 |
-
analysis_mode = st.selectbox(
|
| 404 |
-
"ANALYSIS_MODE",
|
| 405 |
-
["Code Analysis", "GitHub Repository"],
|
| 406 |
-
format_func=lambda x: f"📝 {x}" if x == "Code Analysis" else f"📦 {x}"
|
| 407 |
-
)
|
| 408 |
-
|
| 409 |
-
# Language selection
|
| 410 |
-
languages = ["auto-detect", "python", "javascript", "java", "cpp", "csharp", "go", "rust"]
|
| 411 |
-
selected_language = st.selectbox(
|
| 412 |
-
"TARGET_LANGUAGE",
|
| 413 |
-
languages,
|
| 414 |
-
format_func=lambda x: x.upper().replace("-", "_")
|
| 415 |
-
)
|
| 416 |
-
|
| 417 |
-
st.markdown("---")
|
| 418 |
-
|
| 419 |
-
# Sample code injection
|
| 420 |
-
st.markdown("#### CODE_INJECTION_SAMPLES")
|
| 421 |
-
|
| 422 |
-
if st.button("🐍 INJECT_PYTHON_SAMPLE"):
|
| 423 |
-
st.session_state.code_input = """def matrix_hack():
|
| 424 |
-
# The Matrix has you...
|
| 425 |
-
reality = "simulation"
|
| 426 |
-
if reality == "simulation":
|
| 427 |
-
print("Wake up, Neo...")
|
| 428 |
-
return True
|
| 429 |
-
return False
|
| 430 |
-
|
| 431 |
-
# Take the red pill
|
| 432 |
-
choice = matrix_hack()
|
| 433 |
-
for i in range(10):
|
| 434 |
-
print(f"Level {i}: {'🟢' if choice else '🔴'}")
|
| 435 |
-
"""
|
| 436 |
-
|
| 437 |
-
if st.button("🟨 INJECT_JAVASCRIPT_SAMPLE"):
|
| 438 |
-
st.session_state.code_input = """function followTheWhiteRabbit(choice) {
|
| 439 |
-
const matrix = {
|
| 440 |
-
red_pill: "truth",
|
| 441 |
-
blue_pill: "ignorance"
|
| 442 |
-
};
|
| 443 |
-
|
| 444 |
-
if (choice === "red_pill") {
|
| 445 |
-
console.log("Welcome to the real world");
|
| 446 |
-
return matrix[choice];
|
| 447 |
-
}
|
| 448 |
-
|
| 449 |
-
return "The story ends, you wake up in your bed...";
|
| 450 |
-
}
|
| 451 |
-
|
| 452 |
-
// The choice is yours
|
| 453 |
-
const reality = followTheWhiteRabbit("red_pill");
|
| 454 |
-
console.log(`Reality: ${reality}`);
|
| 455 |
-
"""
|
| 456 |
-
|
| 457 |
-
# Main Terminal Interface
|
| 458 |
-
col1, col2 = st.columns([1, 1])
|
| 459 |
-
|
| 460 |
-
with col1:
|
| 461 |
-
if analysis_mode == "Code Analysis":
|
| 462 |
-
st.markdown("### 📟 CODE_INPUT_TERMINAL")
|
| 463 |
-
|
| 464 |
-
# Code input with Matrix styling
|
| 465 |
-
code_input = st.text_area(
|
| 466 |
-
"PASTE_TARGET_CODE",
|
| 467 |
-
value=st.session_state.get('code_input', ''),
|
| 468 |
-
height=400,
|
| 469 |
-
key="code_input",
|
| 470 |
-
help="Insert code for neural network analysis..."
|
| 471 |
-
)
|
| 472 |
-
|
| 473 |
-
# Matrix-styled analyze button
|
| 474 |
-
analyze_button = st.button(
|
| 475 |
-
"🚀 INITIATE_SCAN",
|
| 476 |
-
type="primary",
|
| 477 |
-
disabled=not code_input.strip(),
|
| 478 |
-
help="Begin deep neural analysis of target code"
|
| 479 |
-
)
|
| 480 |
-
|
| 481 |
-
else: # GitHub Repository mode
|
| 482 |
-
st.markdown("### 📦 GITHUB_REPOSITORY_TERMINAL")
|
| 483 |
-
|
| 484 |
-
# GitHub URL input
|
| 485 |
-
github_url = st.text_input(
|
| 486 |
-
"TARGET_REPOSITORY_URL",
|
| 487 |
-
placeholder="https://github.com/owner/repo",
|
| 488 |
-
help="Enter GitHub repository URL for analysis"
|
| 489 |
-
)
|
| 490 |
-
|
| 491 |
-
# GitHub analyze button
|
| 492 |
-
analyze_github_button = st.button(
|
| 493 |
-
"🔍 SCAN_REPOSITORY",
|
| 494 |
-
type="primary",
|
| 495 |
-
disabled=not github_url.strip(),
|
| 496 |
-
help="Begin neural analysis of GitHub repository"
|
| 497 |
-
)
|
| 498 |
-
|
| 499 |
-
# Initialize code_input for compatibility
|
| 500 |
-
code_input = ""
|
| 501 |
-
analyze_button = False
|
| 502 |
-
|
| 503 |
-
# Results Terminal
|
| 504 |
-
with col2:
|
| 505 |
-
st.markdown("### 📊 ANALYSIS_OUTPUT_TERMINAL")
|
| 506 |
-
|
| 507 |
-
if (analyze_button and code_input.strip()) or (analysis_mode == "GitHub Repository" and 'analyze_github_button' in locals() and analyze_github_button and github_url.strip()):
|
| 508 |
-
with st.spinner("🟢 SCANNING... NEURAL_NETWORKS_PROCESSING..."):
|
| 509 |
-
if analysis_mode == "GitHub Repository":
|
| 510 |
-
# GitHub Repository Analysis
|
| 511 |
-
st.markdown("#### 📦 GITHUB_REPOSITORY_SCAN_INITIATED")
|
| 512 |
-
|
| 513 |
-
if analyze_all:
|
| 514 |
-
# Multi-model GitHub analysis
|
| 515 |
-
results = {}
|
| 516 |
-
for model_key in available_models.keys():
|
| 517 |
-
result = analyzer.analyze_github_repo(github_url, model_key)
|
| 518 |
-
results[model_key] = result
|
| 519 |
-
|
| 520 |
-
# Display comparison metrics for GitHub
|
| 521 |
-
comparison = analyzer.compare_analyses(results)
|
| 522 |
-
|
| 523 |
-
col_metrics = st.columns(4)
|
| 524 |
-
with col_metrics[0]:
|
| 525 |
-
st.metric("REPOSITORY", "ANALYZED")
|
| 526 |
-
with col_metrics[1]:
|
| 527 |
-
st.metric("MODELS_USED", len(results))
|
| 528 |
-
with col_metrics[2]:
|
| 529 |
-
st.metric("CONSENSUS_SCORE", f"{comparison.get('consensus_score', 0):.1f}")
|
| 530 |
-
with col_metrics[3]:
|
| 531 |
-
st.metric("SCAN_TIME", f"{comparison['analysis_time']:.1f}s")
|
| 532 |
-
|
| 533 |
-
# Create tabs for each neural network
|
| 534 |
-
tab_names = [f"🤖 {available_models[key]}" for key in results.keys()]
|
| 535 |
-
tabs = st.tabs(tab_names)
|
| 536 |
-
|
| 537 |
-
for idx, (model_key, result) in enumerate(results.items()):
|
| 538 |
-
with tabs[idx]:
|
| 539 |
-
display_matrix_analysis_result(result, available_models[model_key])
|
| 540 |
-
else:
|
| 541 |
-
# Single model GitHub analysis
|
| 542 |
-
st.markdown(f"#### 🤖 {available_models[selected_model].upper()}_GITHUB_ANALYSIS")
|
| 543 |
-
|
| 544 |
-
result = analyzer.analyze_github_repo(github_url, selected_model)
|
| 545 |
-
display_matrix_analysis_result(result, available_models[selected_model])
|
| 546 |
-
|
| 547 |
-
elif analyze_all:
|
| 548 |
-
# Multi-model code analysis
|
| 549 |
-
st.markdown("#### 🔄 MULTI_NETWORK_ANALYSIS_INITIATED")
|
| 550 |
-
|
| 551 |
-
results = analyzer.analyze_with_all_models(
|
| 552 |
-
code_input,
|
| 553 |
-
selected_language if selected_language != "auto-detect" else None
|
| 554 |
-
)
|
| 555 |
-
|
| 556 |
-
# Display comparison metrics
|
| 557 |
-
comparison = analyzer.compare_analyses(results)
|
| 558 |
-
|
| 559 |
-
# Matrix-styled metrics
|
| 560 |
-
metrics_cols = st.columns(4)
|
| 561 |
-
with metrics_cols[0]:
|
| 562 |
-
st.metric("AVG_SCORE", f"{comparison['average_score']}/100")
|
| 563 |
-
with metrics_cols[1]:
|
| 564 |
-
st.metric("NETWORKS", len(results))
|
| 565 |
-
with metrics_cols[2]:
|
| 566 |
-
st.metric("PEAK_SCORE", f"{max(comparison['model_scores'].values())}/100")
|
| 567 |
-
with metrics_cols[3]:
|
| 568 |
-
st.metric("SCAN_TIME", f"{comparison['analysis_time']:.1f}s")
|
| 569 |
-
|
| 570 |
-
# Create tabs for each neural network
|
| 571 |
-
tab_names = [f"🤖 {available_models[key]}" for key in results.keys()]
|
| 572 |
-
tabs = st.tabs(tab_names)
|
| 573 |
-
|
| 574 |
-
for idx, (model_key, result) in enumerate(results.items()):
|
| 575 |
-
with tabs[idx]:
|
| 576 |
-
display_matrix_analysis_result(result, available_models[model_key])
|
| 577 |
-
|
| 578 |
-
# Consensus findings with Matrix styling
|
| 579 |
-
if comparison['consensus_issues']:
|
| 580 |
-
st.markdown("### 🤝 NEURAL_CONSENSUS_DETECTED")
|
| 581 |
-
st.markdown("""
|
| 582 |
-
<div style="background: rgba(255, 0, 0, 0.1); border: 2px solid #ff0000; padding: 15px; border-radius: 10px;">
|
| 583 |
-
<strong>CRITICAL_PATTERNS_IDENTIFIED_BY_MULTIPLE_NETWORKS:</strong>
|
| 584 |
-
</div>
|
| 585 |
-
""", unsafe_allow_html=True)
|
| 586 |
-
|
| 587 |
-
for issue in comparison['consensus_issues']:
|
| 588 |
-
st.error(f"🚨 CONSENSUS_ALERT: {issue}")
|
| 589 |
-
|
| 590 |
-
else:
|
| 591 |
-
# Single model analysis
|
| 592 |
-
st.markdown(f"#### 🤖 {available_models[selected_model].upper()}_ANALYSIS")
|
| 593 |
-
|
| 594 |
-
result = analyzer.analyze_code(
|
| 595 |
-
code_input,
|
| 596 |
-
selected_model,
|
| 597 |
-
selected_language if selected_language != "auto-detect" else None
|
| 598 |
-
)
|
| 599 |
-
display_matrix_analysis_result(result, available_models[selected_model])
|
| 600 |
-
|
| 601 |
-
# Instructions for new users
|
| 602 |
-
if (analysis_mode == "Code Analysis" and not code_input.strip() and not analyze_button) or (analysis_mode == "GitHub Repository" and 'github_url' not in locals()):
|
| 603 |
-
st.markdown("""
|
| 604 |
-
<div class="matrix-terminal" style="margin: 20px 0;">
|
| 605 |
-
<h3 style="color: #00ff41; text-align: center;">🟢 WELCOME TO THE MATRIX 🟢</h3>
|
| 606 |
-
<p style="color: #00ff41; font-family: 'Share Tech Mono', monospace;">
|
| 607 |
-
> SYSTEM_STATUS: ONLINE<br>
|
| 608 |
-
> NEURAL_NETWORKS: READY<br>
|
| 609 |
-
> ANALYSIS_MODES: CODE_SCAN • REPOSITORY_SCAN<br>
|
| 610 |
-
> AWAITING_INPUT...<br><br>
|
| 611 |
-
|
| 612 |
-
<strong>INITIALIZATION_PROTOCOL:</strong><br>
|
| 613 |
-
📝 CODE_ANALYSIS_MODE:<br>
|
| 614 |
-
1. PASTE_CODE → Left terminal<br>
|
| 615 |
-
2. SELECT_NEURAL_NETWORK → Control panel<br>
|
| 616 |
-
3. INITIATE_SCAN → Begin analysis<br>
|
| 617 |
-
4. REVIEW_RESULTS → Right terminal<br><br>
|
| 618 |
-
|
| 619 |
-
📦 GITHUB_REPOSITORY_MODE:<br>
|
| 620 |
-
1. ENTER_REPOSITORY_URL → Left terminal<br>
|
| 621 |
-
2. SELECT_NEURAL_NETWORK → Control panel<br>
|
| 622 |
-
3. SCAN_REPOSITORY → Begin analysis<br>
|
| 623 |
-
4. REVIEW_RESULTS → Right terminal<br><br>
|
| 624 |
-
|
| 625 |
-
<em>The Matrix has you... but now you have the power to analyze it. 🟢</em>
|
| 626 |
-
</p>
|
| 627 |
-
</div>
|
| 628 |
-
""", unsafe_allow_html=True)
|
| 629 |
-
|
| 630 |
-
# Footer with Matrix signature
|
| 631 |
-
st.markdown("---")
|
| 632 |
-
st.markdown("""
|
| 633 |
-
<div style="text-align: center; color: #00ff41; font-family: 'Share Tech Mono', monospace; padding: 20px;">
|
| 634 |
-
<p>🟢 POWERED_BY_NEURAL_NETWORKS • OPENAI • ANTHROPIC • DEEPSEEK • GOOGLE 🟢</p>
|
| 635 |
-
<p><em>"There is no spoon... only code."</em></p>
|
| 636 |
-
<p style="font-size: 12px;">MATRIX_ANALYZER_v2.0 • BUILD_2024 • SECURITY_CLEARANCE_OMEGA</p>
|
| 637 |
-
</div>
|
| 638 |
-
""", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
matrix_final.py
CHANGED
|
@@ -5,6 +5,7 @@ import random
|
|
| 5 |
import sys
|
| 6 |
from dotenv import load_dotenv
|
| 7 |
from analyzer import CodeAnalyzer
|
|
|
|
| 8 |
|
| 9 |
# Load environment variables
|
| 10 |
load_dotenv()
|
|
@@ -269,7 +270,7 @@ setTimeout(createMatrixRain, 100);
|
|
| 269 |
</script>
|
| 270 |
""", unsafe_allow_html=True)
|
| 271 |
|
| 272 |
-
# Initialize
|
| 273 |
def get_analyzer():
|
| 274 |
# Force reimport to ensure latest code
|
| 275 |
import importlib
|
|
@@ -280,6 +281,16 @@ def get_analyzer():
|
|
| 280 |
|
| 281 |
analyzer = get_analyzer()
|
| 282 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
def display_matrix_analysis_result(result: dict, model_name: str):
|
| 284 |
"""Display analysis result in clean, readable horizontal blocks."""
|
| 285 |
if 'error' in result:
|
|
@@ -601,6 +612,16 @@ with st.sidebar:
|
|
| 601 |
["Code Analysis", "GitHub Repository"],
|
| 602 |
format_func=lambda x: f"📝 {x}" if x == "Code Analysis" else f"📦 {x}"
|
| 603 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 604 |
|
| 605 |
if analysis_mode == "GitHub Repository":
|
| 606 |
st.markdown("#### Repository Analysis")
|
|
@@ -621,11 +642,12 @@ with st.sidebar:
|
|
| 621 |
# Analysis options
|
| 622 |
st.markdown("#### Analysis Settings")
|
| 623 |
|
| 624 |
-
# Model selector with modern styling
|
| 625 |
selected_model = st.selectbox(
|
| 626 |
"Choose AI Model",
|
| 627 |
options=list(available_models.keys()),
|
| 628 |
-
format_func=lambda x: f"🤖 {available_models[x]}"
|
|
|
|
| 629 |
)
|
| 630 |
|
| 631 |
# Multi-model analysis toggle
|
|
@@ -833,14 +855,48 @@ with col2:
|
|
| 833 |
|
| 834 |
else:
|
| 835 |
# Single model analysis
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
|
| 842 |
-
|
| 843 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 844 |
|
| 845 |
# GitHub Analysis Results
|
| 846 |
else: # GitHub Repository mode
|
|
|
|
| 5 |
import sys
|
| 6 |
from dotenv import load_dotenv
|
| 7 |
from analyzer import CodeAnalyzer
|
| 8 |
+
from optimized_code_analyzer import OptimizedCodeAnalyzer
|
| 9 |
|
| 10 |
# Load environment variables
|
| 11 |
load_dotenv()
|
|
|
|
| 270 |
</script>
|
| 271 |
""", unsafe_allow_html=True)
|
| 272 |
|
| 273 |
+
# Initialize analyzers
|
| 274 |
def get_analyzer():
|
| 275 |
# Force reimport to ensure latest code
|
| 276 |
import importlib
|
|
|
|
| 281 |
|
| 282 |
analyzer = get_analyzer()
|
| 283 |
|
| 284 |
+
# Local CodeT5+ analyzer (cached)
|
| 285 |
+
@st.cache_resource
|
| 286 |
+
def get_local_analyzer():
|
| 287 |
+
return OptimizedCodeAnalyzer(
|
| 288 |
+
model_id="Salesforce/codet5p-220m",
|
| 289 |
+
precision="fp16", # fastest from benchmark
|
| 290 |
+
quick_max_new_tokens=180,
|
| 291 |
+
detailed_max_new_tokens=240,
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
def display_matrix_analysis_result(result: dict, model_name: str):
|
| 295 |
"""Display analysis result in clean, readable horizontal blocks."""
|
| 296 |
if 'error' in result:
|
|
|
|
| 612 |
["Code Analysis", "GitHub Repository"],
|
| 613 |
format_func=lambda x: f"📝 {x}" if x == "Code Analysis" else f"📦 {x}"
|
| 614 |
)
|
| 615 |
+
|
| 616 |
+
# Local model toggle and preset
|
| 617 |
+
use_local = st.checkbox("💻 Use Local CodeT5+ (no external API)", value=False)
|
| 618 |
+
local_preset = st.selectbox(
|
| 619 |
+
"Local Inference Mode",
|
| 620 |
+
["Quick", "Detailed"],
|
| 621 |
+
index=0,
|
| 622 |
+
help="Quick = beams 1, ~180 tokens. Detailed = beams 2, ~240 tokens.",
|
| 623 |
+
disabled=not use_local,
|
| 624 |
+
)
|
| 625 |
|
| 626 |
if analysis_mode == "GitHub Repository":
|
| 627 |
st.markdown("#### Repository Analysis")
|
|
|
|
| 642 |
# Analysis options
|
| 643 |
st.markdown("#### Analysis Settings")
|
| 644 |
|
| 645 |
+
# Model selector with modern styling (disabled when using local)
|
| 646 |
selected_model = st.selectbox(
|
| 647 |
"Choose AI Model",
|
| 648 |
options=list(available_models.keys()),
|
| 649 |
+
format_func=lambda x: f"🤖 {available_models[x]}",
|
| 650 |
+
disabled=use_local,
|
| 651 |
)
|
| 652 |
|
| 653 |
# Multi-model analysis toggle
|
|
|
|
| 855 |
|
| 856 |
else:
|
| 857 |
# Single model analysis
|
| 858 |
+
if use_local:
|
| 859 |
+
st.markdown("#### 🤖 CODET5+_LOCAL_ANALYSIS")
|
| 860 |
+
local = get_local_analyzer()
|
| 861 |
+
if local_preset == "Quick":
|
| 862 |
+
result = local.analyze_code_fast(code_input, mode="quick")
|
| 863 |
+
# adapt to display format
|
| 864 |
+
display_matrix_analysis_result({
|
| 865 |
+
"quality_score": result.get("quality_score", 0),
|
| 866 |
+
"summary": "",
|
| 867 |
+
"bugs": [],
|
| 868 |
+
"quality_issues": [],
|
| 869 |
+
"security_vulnerabilities": [],
|
| 870 |
+
"quick_fixes": [],
|
| 871 |
+
"language": "auto",
|
| 872 |
+
"line_count": len(code_input.splitlines()),
|
| 873 |
+
"raw_response": result["analysis"],
|
| 874 |
+
}, "CodeT5+ Local (Quick)")
|
| 875 |
+
else:
|
| 876 |
+
# streaming path – consume generator and show final
|
| 877 |
+
local = get_local_analyzer()
|
| 878 |
+
final_text = None
|
| 879 |
+
for chunk in local.analyze_code_streaming(code_input, show_progress=True, mode="detailed"):
|
| 880 |
+
final_text = chunk
|
| 881 |
+
display_matrix_analysis_result({
|
| 882 |
+
"quality_score": 0,
|
| 883 |
+
"summary": "",
|
| 884 |
+
"bugs": [],
|
| 885 |
+
"quality_issues": [],
|
| 886 |
+
"security_vulnerabilities": [],
|
| 887 |
+
"quick_fixes": [],
|
| 888 |
+
"language": "auto",
|
| 889 |
+
"line_count": len(code_input.splitlines()),
|
| 890 |
+
"raw_response": final_text or "",
|
| 891 |
+
}, "CodeT5+ Local (Detailed)")
|
| 892 |
+
else:
|
| 893 |
+
st.markdown(f"#### 🤖 {available_models[selected_model].upper()}_ANALYSIS")
|
| 894 |
+
result = analyzer.analyze_code(
|
| 895 |
+
code_input,
|
| 896 |
+
selected_model,
|
| 897 |
+
selected_language if selected_language != "auto-detect" else None
|
| 898 |
+
)
|
| 899 |
+
display_matrix_analysis_result(result, available_models[selected_model])
|
| 900 |
|
| 901 |
# GitHub Analysis Results
|
| 902 |
else: # GitHub Repository mode
|
matrix_final_backup.py
DELETED
|
@@ -1,978 +0,0 @@
|
|
| 1 |
-
import streamlit as st
|
| 2 |
-
import os
|
| 3 |
-
import time
|
| 4 |
-
import random
|
| 5 |
-
import sys
|
| 6 |
-
from dotenv import load_dotenv
|
| 7 |
-
from analyzer import CodeAnalyzer
|
| 8 |
-
|
| 9 |
-
# Load environment variables
|
| 10 |
-
load_dotenv()
|
| 11 |
-
|
| 12 |
-
# Page config
|
| 13 |
-
st.set_page_config(
|
| 14 |
-
page_title="Matrix Code Analyzer - Final",
|
| 15 |
-
page_icon="🟢",
|
| 16 |
-
layout="wide",
|
| 17 |
-
initial_sidebar_state="expanded"
|
| 18 |
-
)
|
| 19 |
-
|
| 20 |
-
# Matrix CSS - Enhanced with file upload styling
|
| 21 |
-
st.markdown("""
|
| 22 |
-
<style>
|
| 23 |
-
@import url('https://fonts.googleapis.com/css2?family=Share+Tech+Mono:wght@400&display=swap');
|
| 24 |
-
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap');
|
| 25 |
-
|
| 26 |
-
/* Matrix Background */
|
| 27 |
-
.stApp {
|
| 28 |
-
background: linear-gradient(135deg, #0d1b0d 0%, #000000 50%, #0d1b0d 100%);
|
| 29 |
-
color: #00ff41;
|
| 30 |
-
font-family: 'Share Tech Mono', monospace;
|
| 31 |
-
}
|
| 32 |
-
|
| 33 |
-
/* Matrix Code Rain Animation */
|
| 34 |
-
.matrix-bg {
|
| 35 |
-
position: fixed;
|
| 36 |
-
top: 0;
|
| 37 |
-
left: 0;
|
| 38 |
-
width: 100%;
|
| 39 |
-
height: 100%;
|
| 40 |
-
overflow: hidden;
|
| 41 |
-
z-index: -1;
|
| 42 |
-
opacity: 0.1;
|
| 43 |
-
}
|
| 44 |
-
|
| 45 |
-
.matrix-char {
|
| 46 |
-
position: absolute;
|
| 47 |
-
color: #00ff41;
|
| 48 |
-
font-family: 'Share Tech Mono', monospace;
|
| 49 |
-
font-size: 14px;
|
| 50 |
-
animation: matrix-fall linear infinite;
|
| 51 |
-
}
|
| 52 |
-
|
| 53 |
-
@keyframes matrix-fall {
|
| 54 |
-
0% { transform: translateY(-100vh); opacity: 1; }
|
| 55 |
-
100% { transform: translateY(100vh); opacity: 0; }
|
| 56 |
-
}
|
| 57 |
-
|
| 58 |
-
/* Main Content Styling */
|
| 59 |
-
.main .block-container {
|
| 60 |
-
padding-top: 2rem;
|
| 61 |
-
background: rgba(0, 0, 0, 0.8);
|
| 62 |
-
border: 1px solid #00ff41;
|
| 63 |
-
border-radius: 10px;
|
| 64 |
-
box-shadow: 0 0 20px rgba(0, 255, 65, 0.3);
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
/* Title Styling */
|
| 68 |
-
h1 {
|
| 69 |
-
font-family: 'Orbitron', monospace !important;
|
| 70 |
-
color: #00ff41 !important;
|
| 71 |
-
text-align: center !important;
|
| 72 |
-
text-shadow: 0 0 10px #00ff41, 0 0 20px #00ff41, 0 0 30px #00ff41;
|
| 73 |
-
font-weight: 900 !important;
|
| 74 |
-
margin-bottom: 2rem !important;
|
| 75 |
-
animation: glow 2s ease-in-out infinite alternate;
|
| 76 |
-
}
|
| 77 |
-
|
| 78 |
-
@keyframes glow {
|
| 79 |
-
from { text-shadow: 0 0 5px #00ff41, 0 0 10px #00ff41, 0 0 15px #00ff41; }
|
| 80 |
-
to { text-shadow: 0 0 10px #00ff41, 0 0 20px #00ff41, 0 0 30px #00ff41; }
|
| 81 |
-
}
|
| 82 |
-
|
| 83 |
-
/* Sidebar Styling */
|
| 84 |
-
.css-1d391kg {
|
| 85 |
-
background: rgba(0, 0, 0, 0.9) !important;
|
| 86 |
-
border: 1px solid #00ff41 !important;
|
| 87 |
-
border-radius: 10px !important;
|
| 88 |
-
}
|
| 89 |
-
|
| 90 |
-
/* Buttons */
|
| 91 |
-
.stButton > button {
|
| 92 |
-
background: linear-gradient(45deg, #003300, #006600) !important;
|
| 93 |
-
color: #00ff41 !important;
|
| 94 |
-
border: 2px solid #00ff41 !important;
|
| 95 |
-
border-radius: 5px !important;
|
| 96 |
-
font-family: 'Orbitron', monospace !important;
|
| 97 |
-
font-weight: bold !important;
|
| 98 |
-
text-transform: uppercase !important;
|
| 99 |
-
transition: all 0.3s ease !important;
|
| 100 |
-
box-shadow: 0 0 10px rgba(0, 255, 65, 0.3) !important;
|
| 101 |
-
}
|
| 102 |
-
|
| 103 |
-
.stButton > button:hover {
|
| 104 |
-
background: linear-gradient(45deg, #006600, #00aa00) !important;
|
| 105 |
-
box-shadow: 0 0 20px rgba(0, 255, 65, 0.6) !important;
|
| 106 |
-
transform: translateY(-2px) !important;
|
| 107 |
-
}
|
| 108 |
-
|
| 109 |
-
/* File uploader styling */
|
| 110 |
-
.stFileUploader > div {
|
| 111 |
-
background: rgba(0, 51, 0, 0.3) !important;
|
| 112 |
-
border: 2px dashed #00ff41 !important;
|
| 113 |
-
border-radius: 10px !important;
|
| 114 |
-
padding: 20px !important;
|
| 115 |
-
}
|
| 116 |
-
|
| 117 |
-
.stFileUploader label {
|
| 118 |
-
color: #00ff41 !important;
|
| 119 |
-
font-family: 'Orbitron', monospace !important;
|
| 120 |
-
font-weight: bold !important;
|
| 121 |
-
}
|
| 122 |
-
|
| 123 |
-
/* Select boxes */
|
| 124 |
-
.stSelectbox > div > div {
|
| 125 |
-
background: rgba(0, 51, 0, 0.8) !important;
|
| 126 |
-
border: 1px solid #00ff41 !important;
|
| 127 |
-
color: #00ff41 !important;
|
| 128 |
-
}
|
| 129 |
-
|
| 130 |
-
/* Text areas */
|
| 131 |
-
.stTextArea > div > div > textarea {
|
| 132 |
-
background: rgba(0, 0, 0, 0.9) !important;
|
| 133 |
-
border: 1px solid #00ff41 !important;
|
| 134 |
-
color: #00ff41 !important;
|
| 135 |
-
font-family: 'Share Tech Mono', monospace !important;
|
| 136 |
-
}
|
| 137 |
-
|
| 138 |
-
/* Metrics */
|
| 139 |
-
.css-1xarl3l {
|
| 140 |
-
background: rgba(0, 51, 0, 0.3) !important;
|
| 141 |
-
border: 1px solid #00ff41 !important;
|
| 142 |
-
border-radius: 5px !important;
|
| 143 |
-
box-shadow: 0 0 10px rgba(0, 255, 65, 0.2) !important;
|
| 144 |
-
}
|
| 145 |
-
|
| 146 |
-
/* Success/Info/Warning messages */
|
| 147 |
-
.stSuccess {
|
| 148 |
-
background: rgba(0, 255, 65, 0.1) !important;
|
| 149 |
-
border: 1px solid #00ff41 !important;
|
| 150 |
-
color: #00ff41 !important;
|
| 151 |
-
}
|
| 152 |
-
|
| 153 |
-
.stInfo {
|
| 154 |
-
background: rgba(0, 255, 255, 0.1) !important;
|
| 155 |
-
border: 1px solid #00ffff !important;
|
| 156 |
-
color: #00ffff !important;
|
| 157 |
-
}
|
| 158 |
-
|
| 159 |
-
.stWarning {
|
| 160 |
-
background: rgba(255, 255, 0, 0.1) !important;
|
| 161 |
-
border: 1px solid #ffff00 !important;
|
| 162 |
-
color: #ffff00 !important;
|
| 163 |
-
}
|
| 164 |
-
|
| 165 |
-
.stError {
|
| 166 |
-
background: rgba(255, 0, 0, 0.1) !important;
|
| 167 |
-
border: 1px solid #ff0000 !important;
|
| 168 |
-
color: #ff0000 !important;
|
| 169 |
-
}
|
| 170 |
-
|
| 171 |
-
/* Code blocks */
|
| 172 |
-
.stCode {
|
| 173 |
-
background: rgba(0, 0, 0, 0.9) !important;
|
| 174 |
-
border: 1px solid #00ff41 !important;
|
| 175 |
-
color: #00ff41 !important;
|
| 176 |
-
}
|
| 177 |
-
|
| 178 |
-
/* Tabs */
|
| 179 |
-
.stTabs [data-baseweb="tab-list"] {
|
| 180 |
-
background: rgba(0, 0, 0, 0.8) !important;
|
| 181 |
-
border-bottom: 2px solid #00ff41 !important;
|
| 182 |
-
}
|
| 183 |
-
|
| 184 |
-
.stTabs [data-baseweb="tab"] {
|
| 185 |
-
background: rgba(0, 51, 0, 0.3) !important;
|
| 186 |
-
color: #00ff41 !important;
|
| 187 |
-
border: 1px solid #00ff41 !important;
|
| 188 |
-
font-family: 'Orbitron', monospace !important;
|
| 189 |
-
}
|
| 190 |
-
|
| 191 |
-
.stTabs [aria-selected="true"] {
|
| 192 |
-
background: rgba(0, 255, 65, 0.2) !important;
|
| 193 |
-
box-shadow: 0 0 10px rgba(0, 255, 65, 0.5) !important;
|
| 194 |
-
}
|
| 195 |
-
|
| 196 |
-
/* Matrix Terminal Effect */
|
| 197 |
-
.matrix-terminal {
|
| 198 |
-
background: rgba(0, 0, 0, 0.95) !important;
|
| 199 |
-
border: 2px solid #00ff41 !important;
|
| 200 |
-
border-radius: 10px !important;
|
| 201 |
-
padding: 20px !important;
|
| 202 |
-
font-family: 'Share Tech Mono', monospace !important;
|
| 203 |
-
color: #00ff41 !important;
|
| 204 |
-
box-shadow: 0 0 30px rgba(0, 255, 65, 0.4) !important;
|
| 205 |
-
position: relative !important;
|
| 206 |
-
}
|
| 207 |
-
|
| 208 |
-
.matrix-terminal::before {
|
| 209 |
-
content: "MATRIX_ANALYZER_v3.0 > OPERATIONAL" !important;
|
| 210 |
-
position: absolute !important;
|
| 211 |
-
top: -15px !important;
|
| 212 |
-
left: 20px !important;
|
| 213 |
-
background: #000000 !important;
|
| 214 |
-
padding: 0 10px !important;
|
| 215 |
-
color: #00ff41 !important;
|
| 216 |
-
font-size: 12px !important;
|
| 217 |
-
font-weight: bold !important;
|
| 218 |
-
}
|
| 219 |
-
|
| 220 |
-
/* Checkbox styling */
|
| 221 |
-
.stCheckbox > label {
|
| 222 |
-
color: #00ff41 !important;
|
| 223 |
-
font-family: 'Orbitron', monospace !important;
|
| 224 |
-
}
|
| 225 |
-
|
| 226 |
-
/* Loading spinner */
|
| 227 |
-
.stSpinner > div {
|
| 228 |
-
border-color: #00ff41 transparent #00ff41 transparent !important;
|
| 229 |
-
}
|
| 230 |
-
|
| 231 |
-
/* Expander */
|
| 232 |
-
.streamlit-expanderHeader {
|
| 233 |
-
background: rgba(0, 51, 0, 0.3) !important;
|
| 234 |
-
border: 1px solid #00ff41 !important;
|
| 235 |
-
color: #00ff41 !important;
|
| 236 |
-
}
|
| 237 |
-
|
| 238 |
-
/* File info styling */
|
| 239 |
-
.file-info {
|
| 240 |
-
background: rgba(0, 255, 65, 0.1);
|
| 241 |
-
border: 1px solid #00ff41;
|
| 242 |
-
padding: 10px;
|
| 243 |
-
border-radius: 5px;
|
| 244 |
-
margin: 10px 0;
|
| 245 |
-
font-family: 'Share Tech Mono', monospace;
|
| 246 |
-
}
|
| 247 |
-
</style>
|
| 248 |
-
|
| 249 |
-
<div class="matrix-bg" id="matrix-bg"></div>
|
| 250 |
-
|
| 251 |
-
<script>
|
| 252 |
-
function createMatrixRain() {
|
| 253 |
-
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()_+-=[]{}|;:,.<>?";
|
| 254 |
-
const container = document.getElementById('matrix-bg');
|
| 255 |
-
|
| 256 |
-
for (let i = 0; i < 50; i++) {
|
| 257 |
-
const char = document.createElement('div');
|
| 258 |
-
char.className = 'matrix-char';
|
| 259 |
-
char.textContent = chars[Math.floor(Math.random() * chars.length)];
|
| 260 |
-
char.style.left = Math.random() * 100 + '%';
|
| 261 |
-
char.style.animationDuration = (Math.random() * 3 + 2) + 's';
|
| 262 |
-
char.style.animationDelay = Math.random() * 2 + 's';
|
| 263 |
-
container.appendChild(char);
|
| 264 |
-
}
|
| 265 |
-
}
|
| 266 |
-
|
| 267 |
-
// Create matrix rain effect
|
| 268 |
-
setTimeout(createMatrixRain, 100);
|
| 269 |
-
</script>
|
| 270 |
-
""", unsafe_allow_html=True)
|
| 271 |
-
|
| 272 |
-
# Initialize analyzer
|
| 273 |
-
def get_analyzer():
|
| 274 |
-
# Force reimport to ensure latest code
|
| 275 |
-
import importlib
|
| 276 |
-
import analyzer.code_analyzer
|
| 277 |
-
importlib.reload(analyzer.code_analyzer)
|
| 278 |
-
from analyzer.code_analyzer import CodeAnalyzer
|
| 279 |
-
return CodeAnalyzer()
|
| 280 |
-
|
| 281 |
-
analyzer = get_analyzer()
|
| 282 |
-
|
| 283 |
-
def display_matrix_analysis_result(result: dict, model_name: str):
|
| 284 |
-
"""Display analysis result in clean, readable horizontal blocks."""
|
| 285 |
-
if 'error' in result:
|
| 286 |
-
st.error(f"🚨 SYSTEM ERROR: {result['error']}")
|
| 287 |
-
return
|
| 288 |
-
|
| 289 |
-
# Quality score with modern styling
|
| 290 |
-
score = result['quality_score']
|
| 291 |
-
if score >= 80:
|
| 292 |
-
score_color = "#00ff41"
|
| 293 |
-
status = "EXCELLENT"
|
| 294 |
-
elif score >= 60:
|
| 295 |
-
score_color = "#ffff00"
|
| 296 |
-
status = "ACCEPTABLE"
|
| 297 |
-
else:
|
| 298 |
-
score_color = "#ff0000"
|
| 299 |
-
status = "NEEDS_WORK"
|
| 300 |
-
|
| 301 |
-
# Header with score
|
| 302 |
-
st.markdown(f"""
|
| 303 |
-
<div style="background: linear-gradient(135deg, rgba(0,255,65,0.15), rgba(0,255,65,0.05));
|
| 304 |
-
border: 2px solid #00ff41; border-radius: 15px; padding: 25px; margin: 20px 0;
|
| 305 |
-
text-align: center;">
|
| 306 |
-
<h2 style="color: {score_color}; margin-bottom: 15px; font-size: 1.8rem;">
|
| 307 |
-
{model_name} Analysis
|
| 308 |
-
</h2>
|
| 309 |
-
<div style="display: flex; justify-content: center; gap: 30px; flex-wrap: wrap; color: #ffffff;">
|
| 310 |
-
<div style="text-align: center;">
|
| 311 |
-
<div style="font-size: 2rem; color: {score_color}; font-weight: bold;">{score}/100</div>
|
| 312 |
-
<div style="font-size: 0.9rem; opacity: 0.8;">{status}</div>
|
| 313 |
-
</div>
|
| 314 |
-
<div style="text-align: center;">
|
| 315 |
-
<div style="font-size: 1.2rem; color: #00ff41; font-weight: bold;">{result['language'].upper()}</div>
|
| 316 |
-
<div style="font-size: 0.9rem; opacity: 0.8;">Language</div>
|
| 317 |
-
</div>
|
| 318 |
-
<div style="text-align: center;">
|
| 319 |
-
<div style="font-size: 1.2rem; color: #00ff41; font-weight: bold;">{result['line_count']}</div>
|
| 320 |
-
<div style="font-size: 0.9rem; opacity: 0.8;">Lines</div>
|
| 321 |
-
</div>
|
| 322 |
-
</div>
|
| 323 |
-
</div>
|
| 324 |
-
""", unsafe_allow_html=True)
|
| 325 |
-
|
| 326 |
-
# Summary
|
| 327 |
-
if result.get('summary'):
|
| 328 |
-
st.markdown("### 📋 Code Overview")
|
| 329 |
-
st.markdown(f"""
|
| 330 |
-
<div style="background: rgba(0,0,0,0.6); border: 1px solid #00ff41; border-radius: 10px;
|
| 331 |
-
padding: 20px; margin: 20px 0;">
|
| 332 |
-
<p style="color: #ffffff; font-size: 18px; line-height: 1.6; text-align: center; margin: 0;">
|
| 333 |
-
{result['summary']}
|
| 334 |
-
</p>
|
| 335 |
-
</div>
|
| 336 |
-
""", unsafe_allow_html=True)
|
| 337 |
-
|
| 338 |
-
# Analysis results in horizontal blocks
|
| 339 |
-
st.markdown("### 📊 Analysis Results")
|
| 340 |
-
|
| 341 |
-
# Bug Detection Block (Full width)
|
| 342 |
-
bug_items = result.get('bugs', [])
|
| 343 |
-
if bug_items:
|
| 344 |
-
bug_text = " • ".join(bug_items[:3]) # Join with bullets for horizontal reading
|
| 345 |
-
else:
|
| 346 |
-
bug_text = "No critical bugs detected • Code logic appears sound • Edge cases handled well"
|
| 347 |
-
|
| 348 |
-
st.markdown(f"""
|
| 349 |
-
<div style="background: linear-gradient(135deg, rgba(255,100,100,0.1), rgba(150,0,0,0.1));
|
| 350 |
-
border: 2px solid #ff6b6b; border-radius: 15px; padding: 25px; margin: 15px 0;">
|
| 351 |
-
<h3 style="color: #ff6b6b; margin-bottom: 15px; text-align: center; font-size: 1.4rem;">
|
| 352 |
-
🐛 Bug Detection
|
| 353 |
-
</h3>
|
| 354 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6; text-align: center; margin: 0;">
|
| 355 |
-
{bug_text}
|
| 356 |
-
</p>
|
| 357 |
-
</div>
|
| 358 |
-
""", unsafe_allow_html=True)
|
| 359 |
-
|
| 360 |
-
# Security Vulnerabilities Block (Full width)
|
| 361 |
-
security_items = result.get('security_vulnerabilities', [])
|
| 362 |
-
if security_items:
|
| 363 |
-
security_text = " • ".join(security_items[:3]) # Join with bullets for horizontal reading
|
| 364 |
-
else:
|
| 365 |
-
security_text = "No security vulnerabilities found • Follows security best practices • Input validation looks good"
|
| 366 |
-
|
| 367 |
-
st.markdown(f"""
|
| 368 |
-
<div style="background: linear-gradient(135deg, rgba(200,0,200,0.1), rgba(100,0,100,0.1));
|
| 369 |
-
border: 2px solid #ff00ff; border-radius: 15px; padding: 25px; margin: 15px 0;">
|
| 370 |
-
<h3 style="color: #ff00ff; margin-bottom: 15px; text-align: center; font-size: 1.4rem;">
|
| 371 |
-
🔒 Security Check
|
| 372 |
-
</h3>
|
| 373 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6; text-align: center; margin: 0;">
|
| 374 |
-
{security_text}
|
| 375 |
-
</p>
|
| 376 |
-
</div>
|
| 377 |
-
""", unsafe_allow_html=True)
|
| 378 |
-
|
| 379 |
-
# Code Quality & Quick Fixes Block (Full width)
|
| 380 |
-
quality_items = result.get('quality_issues', []) + result.get('quick_fixes', [])
|
| 381 |
-
if quality_items:
|
| 382 |
-
quality_text = " • ".join(quality_items[:3]) # Join with bullets for horizontal reading
|
| 383 |
-
else:
|
| 384 |
-
quality_text = "Code is well-structured • Good naming conventions • Easy to read and maintain"
|
| 385 |
-
|
| 386 |
-
st.markdown(f"""
|
| 387 |
-
<div style="background: linear-gradient(135deg, rgba(0,200,255,0.1), rgba(0,100,150,0.1));
|
| 388 |
-
border: 2px solid #00ccff; border-radius: 15px; padding: 25px; margin: 15px 0;">
|
| 389 |
-
<h3 style="color: #00ccff; margin-bottom: 15px; text-align: center; font-size: 1.4rem;">
|
| 390 |
-
📝 Code Quality
|
| 391 |
-
</h3>
|
| 392 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6; text-align: center; margin: 0;">
|
| 393 |
-
{quality_text}
|
| 394 |
-
</p>
|
| 395 |
-
</div>
|
| 396 |
-
""", unsafe_allow_html=True)
|
| 397 |
-
|
| 398 |
-
# Legacy sections (only if new sections are empty)
|
| 399 |
-
if not result.get('bugs') and not result.get('security_vulnerabilities') and not result.get('quality_issues'):
|
| 400 |
-
legacy_col1, legacy_col2 = st.columns(2)
|
| 401 |
-
|
| 402 |
-
with legacy_col1:
|
| 403 |
-
# Legacy strengths
|
| 404 |
-
if result.get('strengths'):
|
| 405 |
-
st.markdown("#### ✅ Strengths")
|
| 406 |
-
for strength in result['strengths'][:3]:
|
| 407 |
-
st.success(f"✓ {strength}")
|
| 408 |
-
|
| 409 |
-
# Legacy issues
|
| 410 |
-
if result.get('issues'):
|
| 411 |
-
st.markdown("#### ⚠️ Issues")
|
| 412 |
-
for issue in result['issues'][:3]:
|
| 413 |
-
st.warning(f"! {issue}")
|
| 414 |
-
|
| 415 |
-
with legacy_col2:
|
| 416 |
-
# Legacy suggestions
|
| 417 |
-
if result.get('suggestions'):
|
| 418 |
-
st.markdown("#### 💡 Suggestions")
|
| 419 |
-
for suggestion in result['suggestions'][:3]:
|
| 420 |
-
st.info(f"→ {suggestion}")
|
| 421 |
-
|
| 422 |
-
# Legacy security concerns
|
| 423 |
-
if result.get('security_concerns'):
|
| 424 |
-
st.markdown("#### 🔒 Security Concerns")
|
| 425 |
-
for concern in result['security_concerns'][:3]:
|
| 426 |
-
st.error(f"⚠ {concern}")
|
| 427 |
-
|
| 428 |
-
# Expandable raw response (moved to bottom and less prominent)
|
| 429 |
-
with st.expander("🔍 View Detailed Analysis", expanded=False):
|
| 430 |
-
st.code(result.get('raw_response', 'NO_DATA_AVAILABLE'), language='text')
|
| 431 |
-
|
| 432 |
-
def display_github_analysis_result(result: dict, model_name: str):
|
| 433 |
-
"""Display GitHub repository analysis result in clean, readable horizontal blocks."""
|
| 434 |
-
if 'error' in result:
|
| 435 |
-
st.error(f"🚨 GITHUB ANALYSIS ERROR: {result['error']}")
|
| 436 |
-
return
|
| 437 |
-
|
| 438 |
-
# Repository info in a clean header
|
| 439 |
-
if result.get('repository_info'):
|
| 440 |
-
repo_info = result['repository_info']
|
| 441 |
-
st.markdown(f"""
|
| 442 |
-
<div style="background: linear-gradient(135deg, rgba(0,255,65,0.15), rgba(0,255,65,0.05));
|
| 443 |
-
border: 2px solid #00ff41; border-radius: 15px; padding: 25px; margin: 20px 0;
|
| 444 |
-
text-align: center;">
|
| 445 |
-
<h2 style="color: #00ff41; margin-bottom: 20px; font-size: 1.8rem;">
|
| 446 |
-
📦 {repo_info['name']}
|
| 447 |
-
</h2>
|
| 448 |
-
<div style="display: flex; justify-content: center; gap: 30px; flex-wrap: wrap; color: #ffffff;">
|
| 449 |
-
<div style="text-align: center;">
|
| 450 |
-
<div style="font-size: 1.5rem; color: #00ff41; font-weight: bold;">{repo_info['language']}</div>
|
| 451 |
-
<div style="font-size: 0.9rem; opacity: 0.8;">Language</div>
|
| 452 |
-
</div>
|
| 453 |
-
<div style="text-align: center;">
|
| 454 |
-
<div style="font-size: 1.5rem; color: #00ff41; font-weight: bold;">⭐ {repo_info['stars']}</div>
|
| 455 |
-
<div style="font-size: 0.9rem; opacity: 0.8;">Stars</div>
|
| 456 |
-
</div>
|
| 457 |
-
<div style="text-align: center;">
|
| 458 |
-
<div style="font-size: 1.5rem; color: #00ff41; font-weight: bold;">🔀 {repo_info['forks']}</div>
|
| 459 |
-
<div style="font-size: 0.9rem; opacity: 0.8;">Forks</div>
|
| 460 |
-
</div>
|
| 461 |
-
</div>
|
| 462 |
-
<p style="color: #ffffff; margin-top: 15px; font-style: italic;">
|
| 463 |
-
"{repo_info['description']}"
|
| 464 |
-
</p>
|
| 465 |
-
</div>
|
| 466 |
-
""", unsafe_allow_html=True)
|
| 467 |
-
|
| 468 |
-
# Analysis results in horizontal blocks
|
| 469 |
-
st.markdown("### 📊 Analysis Results")
|
| 470 |
-
|
| 471 |
-
# Architecture Quality Block (Full width)
|
| 472 |
-
arch_items = result.get('architecture_quality', [])
|
| 473 |
-
if arch_items:
|
| 474 |
-
arch_text = " • ".join(arch_items[:3]) # Join with bullets for horizontal reading
|
| 475 |
-
else:
|
| 476 |
-
arch_text = "Well-structured repository • Good organization • Follows best practices"
|
| 477 |
-
|
| 478 |
-
st.markdown(f"""
|
| 479 |
-
<div style="background: linear-gradient(135deg, rgba(0,255,65,0.1), rgba(0,100,30,0.1));
|
| 480 |
-
border: 2px solid #00ff41; border-radius: 15px; padding: 25px; margin: 15px 0;">
|
| 481 |
-
<h3 style="color: #00ff41; margin-bottom: 15px; text-align: center; font-size: 1.4rem;">
|
| 482 |
-
🏗️ Code Architecture
|
| 483 |
-
</h3>
|
| 484 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6; text-align: center; margin: 0;">
|
| 485 |
-
{arch_text}
|
| 486 |
-
</p>
|
| 487 |
-
</div>
|
| 488 |
-
""", unsafe_allow_html=True)
|
| 489 |
-
|
| 490 |
-
# Critical Issues Block (Full width)
|
| 491 |
-
critical_items = result.get('critical_issues', [])
|
| 492 |
-
if critical_items:
|
| 493 |
-
critical_text = " • ".join(critical_items[:3]) # Join with bullets for horizontal reading
|
| 494 |
-
else:
|
| 495 |
-
critical_text = "No major security vulnerabilities found • Code appears well-maintained • No critical bugs detected"
|
| 496 |
-
|
| 497 |
-
st.markdown(f"""
|
| 498 |
-
<div style="background: linear-gradient(135deg, rgba(255,100,100,0.1), rgba(150,0,0,0.1));
|
| 499 |
-
border: 2px solid #ff6b6b; border-radius: 15px; padding: 25px; margin: 15px 0;">
|
| 500 |
-
<h3 style="color: #ff6b6b; margin-bottom: 15px; text-align: center; font-size: 1.4rem;">
|
| 501 |
-
🚨 Critical Issues
|
| 502 |
-
</h3>
|
| 503 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6; text-align: center; margin: 0;">
|
| 504 |
-
{critical_text}
|
| 505 |
-
</p>
|
| 506 |
-
</div>
|
| 507 |
-
""", unsafe_allow_html=True)
|
| 508 |
-
|
| 509 |
-
# Improvement Priorities Block (Full width)
|
| 510 |
-
improvement_items = result.get('improvement_priorities', [])
|
| 511 |
-
if improvement_items:
|
| 512 |
-
improvement_text = " • ".join(improvement_items[:3]) # Join with bullets for horizontal reading
|
| 513 |
-
else:
|
| 514 |
-
improvement_text = "Add more comprehensive documentation • Consider adding automated tests • Enhance error handling"
|
| 515 |
-
|
| 516 |
-
st.markdown(f"""
|
| 517 |
-
<div style="background: linear-gradient(135deg, rgba(255,200,0,0.1), rgba(150,100,0,0.1));
|
| 518 |
-
border: 2px solid #ffd700; border-radius: 15px; padding: 25px; margin: 15px 0;">
|
| 519 |
-
<h3 style="color: #ffd700; margin-bottom: 15px; text-align: center; font-size: 1.4rem;">
|
| 520 |
-
🎯 Priority Improvements
|
| 521 |
-
</h3>
|
| 522 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6; text-align: center; margin: 0;">
|
| 523 |
-
{improvement_text}
|
| 524 |
-
</p>
|
| 525 |
-
</div>
|
| 526 |
-
""", unsafe_allow_html=True)
|
| 527 |
-
|
| 528 |
-
# Summary section at the bottom (if available)
|
| 529 |
-
if result.get('project_overview'):
|
| 530 |
-
st.markdown("### 💡 Key Insights")
|
| 531 |
-
st.markdown(f"""
|
| 532 |
-
<div style="background: rgba(0,0,0,0.6); border: 1px solid #00ff41; border-radius: 10px;
|
| 533 |
-
padding: 20px; margin: 20px 0;">
|
| 534 |
-
<p style="color: #ffffff; font-size: 18px; line-height: 1.6; text-align: center; margin: 0;">
|
| 535 |
-
{result['project_overview']}
|
| 536 |
-
</p>
|
| 537 |
-
</div>
|
| 538 |
-
""", unsafe_allow_html=True)
|
| 539 |
-
|
| 540 |
-
# Expandable raw response (moved to bottom and less prominent)
|
| 541 |
-
with st.expander("🔍 View Detailed Analysis", expanded=False):
|
| 542 |
-
st.code(result.get('raw_response', 'NO_DATA_AVAILABLE'), language='text')
|
| 543 |
-
|
| 544 |
-
# Header with Matrix effect
|
| 545 |
-
st.markdown("""
|
| 546 |
-
<h1 style="text-align: center;">
|
| 547 |
-
🤖 AI Code Analyzer
|
| 548 |
-
</h1>
|
| 549 |
-
<div style="text-align: center; margin-bottom: 30px;">
|
| 550 |
-
<p style="color: #00ff41; font-family: 'Orbitron', monospace; font-size: 20px; margin-bottom: 10px;">
|
| 551 |
-
<strong>Powered by Advanced AI Models</strong>
|
| 552 |
-
</p>
|
| 553 |
-
<div style="display: flex; justify-content: center; gap: 20px; flex-wrap: wrap;">
|
| 554 |
-
<span style="background: rgba(0,255,65,0.2); border: 1px solid #00ff41; padding: 8px 16px;
|
| 555 |
-
border-radius: 25px; font-size: 14px; color: #00ff41;">
|
| 556 |
-
✨ Bug Detection
|
| 557 |
-
</span>
|
| 558 |
-
<span style="background: rgba(0,255,65,0.2); border: 1px solid #00ff41; padding: 8px 16px;
|
| 559 |
-
border-radius: 25px; font-size: 14px; color: #00ff41;">
|
| 560 |
-
🔒 Security Analysis
|
| 561 |
-
</span>
|
| 562 |
-
<span style="background: rgba(0,255,65,0.2); border: 1px solid #00ff41; padding: 8px 16px;
|
| 563 |
-
border-radius: 25px; font-size: 14px; color: #00ff41;">
|
| 564 |
-
📦 GitHub Integration
|
| 565 |
-
</span>
|
| 566 |
-
<span style="background: rgba(0,255,65,0.2); border: 1px solid #00ff41; padding: 8px 16px;
|
| 567 |
-
border-radius: 25px; font-size: 14px; color: #00ff41;">
|
| 568 |
-
⚡ Instant Results
|
| 569 |
-
</span>
|
| 570 |
-
</div>
|
| 571 |
-
</div>
|
| 572 |
-
""", unsafe_allow_html=True)
|
| 573 |
-
|
| 574 |
-
# Sidebar - The Matrix Control Panel
|
| 575 |
-
with st.sidebar:
|
| 576 |
-
st.markdown("### 🎛️ Control Panel")
|
| 577 |
-
|
| 578 |
-
# Model status
|
| 579 |
-
st.markdown("#### Available AI Models")
|
| 580 |
-
available_models = analyzer.available_models
|
| 581 |
-
|
| 582 |
-
if not available_models:
|
| 583 |
-
st.error("❌ No AI models detected")
|
| 584 |
-
st.info("Please configure API keys in .env file")
|
| 585 |
-
st.stop()
|
| 586 |
-
|
| 587 |
-
# Display available models with modern styling
|
| 588 |
-
for model, display_name in available_models.items():
|
| 589 |
-
st.markdown(f"""
|
| 590 |
-
<div style="background: rgba(0, 255, 65, 0.1); border: 1px solid #00ff41; padding: 10px; margin: 8px 0; border-radius: 8px;">
|
| 591 |
-
✅ <strong>{display_name}</strong> <span style="color: #00ff41; font-size: 12px;">[Ready]</span>
|
| 592 |
-
</div>
|
| 593 |
-
""", unsafe_allow_html=True)
|
| 594 |
-
|
| 595 |
-
st.markdown("---")
|
| 596 |
-
|
| 597 |
-
# Analysis Mode Selection
|
| 598 |
-
st.markdown("#### Analysis Mode")
|
| 599 |
-
analysis_mode = st.radio(
|
| 600 |
-
"Choose what to analyze",
|
| 601 |
-
["Code Analysis", "GitHub Repository"],
|
| 602 |
-
format_func=lambda x: f"📝 {x}" if x == "Code Analysis" else f"📦 {x}"
|
| 603 |
-
)
|
| 604 |
-
|
| 605 |
-
if analysis_mode == "GitHub Repository":
|
| 606 |
-
st.markdown("#### Repository Analysis")
|
| 607 |
-
github_url = st.text_input(
|
| 608 |
-
"GitHub URL",
|
| 609 |
-
placeholder="https://github.com/owner/repo",
|
| 610 |
-
help="Enter a GitHub repository URL for analysis"
|
| 611 |
-
)
|
| 612 |
-
|
| 613 |
-
analyze_github_button = st.button(
|
| 614 |
-
"🔍 Analyze Repository",
|
| 615 |
-
type="primary",
|
| 616 |
-
help="Analyze GitHub repository structure and code"
|
| 617 |
-
)
|
| 618 |
-
|
| 619 |
-
st.markdown("---")
|
| 620 |
-
|
| 621 |
-
# Analysis options
|
| 622 |
-
st.markdown("#### Analysis Settings")
|
| 623 |
-
|
| 624 |
-
# Model selector with modern styling
|
| 625 |
-
selected_model = st.selectbox(
|
| 626 |
-
"Choose AI Model",
|
| 627 |
-
options=list(available_models.keys()),
|
| 628 |
-
format_func=lambda x: f"🤖 {available_models[x]}"
|
| 629 |
-
)
|
| 630 |
-
|
| 631 |
-
# Multi-model analysis toggle
|
| 632 |
-
analyze_all = st.checkbox("🔄 Compare Multiple Models", value=False)
|
| 633 |
-
|
| 634 |
-
# Language selection
|
| 635 |
-
languages = ["auto-detect", "python", "javascript", "java", "cpp", "csharp", "go", "rust", "php", "ruby", "swift", "kotlin"]
|
| 636 |
-
selected_language = st.selectbox(
|
| 637 |
-
"Programming Language",
|
| 638 |
-
languages,
|
| 639 |
-
format_func=lambda x: "🔍 Auto-Detect" if x == "auto-detect" else f"💻 {x.upper()}"
|
| 640 |
-
)
|
| 641 |
-
|
| 642 |
-
st.markdown("---")
|
| 643 |
-
|
| 644 |
-
# Sample code injection
|
| 645 |
-
st.markdown("#### Quick Start Examples")
|
| 646 |
-
|
| 647 |
-
if st.button("🐍 Try Python Example"):
|
| 648 |
-
st.session_state.code_input = """def calculate_total(items):
|
| 649 |
-
total = 0
|
| 650 |
-
for item in items:
|
| 651 |
-
total += item.price # Potential AttributeError
|
| 652 |
-
return total
|
| 653 |
-
|
| 654 |
-
# Missing validation
|
| 655 |
-
items = None
|
| 656 |
-
result = calculate_total(items) # This will crash
|
| 657 |
-
print(f"Total: {result}")
|
| 658 |
-
"""
|
| 659 |
-
|
| 660 |
-
if st.button("🌐 Try JavaScript Example"):
|
| 661 |
-
st.session_state.code_input = """function processUser(user) {
|
| 662 |
-
// Security issue: no input validation
|
| 663 |
-
document.innerHTML = user.name; // XSS vulnerability
|
| 664 |
-
|
| 665 |
-
// Logic error: undefined check
|
| 666 |
-
if (user.age > 18) {
|
| 667 |
-
return user.permissions.admin; // Potential TypeError
|
| 668 |
-
}
|
| 669 |
-
|
| 670 |
-
return false;
|
| 671 |
-
}
|
| 672 |
-
|
| 673 |
-
// Missing error handling
|
| 674 |
-
const userData = getUser(); // Could be undefined
|
| 675 |
-
processUser(userData);
|
| 676 |
-
"""
|
| 677 |
-
|
| 678 |
-
# Main Terminal Interface
|
| 679 |
-
col1, col2 = st.columns([1, 1])
|
| 680 |
-
|
| 681 |
-
with col1:
|
| 682 |
-
if analysis_mode == "Code Analysis":
|
| 683 |
-
st.markdown("### 📝 Code Input")
|
| 684 |
-
|
| 685 |
-
# File upload section
|
| 686 |
-
st.markdown("#### 📁 Upload File")
|
| 687 |
-
uploaded_file = st.file_uploader(
|
| 688 |
-
"Choose a code file",
|
| 689 |
-
type=['py', 'js', 'java', 'cpp', 'c', 'cs', 'go', 'rs', 'php', 'rb', 'swift', 'kt', 'txt'],
|
| 690 |
-
help="Upload code files for AI analysis"
|
| 691 |
-
)
|
| 692 |
-
|
| 693 |
-
code_from_file = ""
|
| 694 |
-
if uploaded_file is not None:
|
| 695 |
-
# Read file content
|
| 696 |
-
try:
|
| 697 |
-
code_from_file = str(uploaded_file.read(), "utf-8")
|
| 698 |
-
file_size = len(code_from_file)
|
| 699 |
-
file_lines = len(code_from_file.splitlines())
|
| 700 |
-
|
| 701 |
-
st.markdown(f"""
|
| 702 |
-
<div class="file-info">
|
| 703 |
-
✅ <strong>File Uploaded Successfully</strong><br>
|
| 704 |
-
📄 <strong>Name:</strong> {uploaded_file.name}<br>
|
| 705 |
-
📏 <strong>Size:</strong> {file_size} bytes<br>
|
| 706 |
-
📊 <strong>Lines:</strong> {file_lines}<br>
|
| 707 |
-
🔍 <strong>Status:</strong> Ready for analysis
|
| 708 |
-
</div>
|
| 709 |
-
""", unsafe_allow_html=True)
|
| 710 |
-
|
| 711 |
-
# Auto-populate the text area
|
| 712 |
-
st.session_state.code_input = code_from_file
|
| 713 |
-
|
| 714 |
-
except UnicodeDecodeError:
|
| 715 |
-
st.error("🚨 File encoding error: Please use UTF-8 encoded files")
|
| 716 |
-
except Exception as e:
|
| 717 |
-
st.error(f"🚨 File read error: {str(e)}")
|
| 718 |
-
|
| 719 |
-
# Code input with modern styling
|
| 720 |
-
code_input = st.text_area(
|
| 721 |
-
"Or paste your code here",
|
| 722 |
-
value=st.session_state.get('code_input', ''),
|
| 723 |
-
height=350,
|
| 724 |
-
key="code_input",
|
| 725 |
-
help="Paste code directly or upload file above"
|
| 726 |
-
)
|
| 727 |
-
|
| 728 |
-
# Modern analyze button
|
| 729 |
-
analyze_button = st.button(
|
| 730 |
-
"🚀 Analyze Code",
|
| 731 |
-
type="primary",
|
| 732 |
-
help="Analyze your code with AI"
|
| 733 |
-
)
|
| 734 |
-
|
| 735 |
-
else: # GitHub Repository mode
|
| 736 |
-
st.markdown("### 📦 GitHub Analysis")
|
| 737 |
-
|
| 738 |
-
if 'github_url' in locals():
|
| 739 |
-
if github_url:
|
| 740 |
-
st.markdown(f"""
|
| 741 |
-
<div class="file-info">
|
| 742 |
-
✅ <strong>Repository Detected</strong><br>
|
| 743 |
-
📦 <strong>URL:</strong> {github_url}<br>
|
| 744 |
-
🔍 <strong>Status:</strong> Ready for analysis
|
| 745 |
-
</div>
|
| 746 |
-
""", unsafe_allow_html=True)
|
| 747 |
-
|
| 748 |
-
st.markdown("""
|
| 749 |
-
#### 📋 What We'll Analyze
|
| 750 |
-
|
| 751 |
-
**Repository Analysis includes:**
|
| 752 |
-
- 🏗️ Project structure and organization
|
| 753 |
-
- 📄 Key files (README, package.json, main source files)
|
| 754 |
-
- 🎯 Code quality and architecture assessment
|
| 755 |
-
- 🔒 Security vulnerabilities across the codebase
|
| 756 |
-
- 💡 Best practices and improvement suggestions
|
| 757 |
-
|
| 758 |
-
**Note:** Only public repositories can be analyzed.
|
| 759 |
-
""")
|
| 760 |
-
|
| 761 |
-
# Show sample repos
|
| 762 |
-
st.markdown("#### 📚 Try These Sample Repositories")
|
| 763 |
-
sample_repos = [
|
| 764 |
-
"https://github.com/microsoft/vscode",
|
| 765 |
-
"https://github.com/facebook/react",
|
| 766 |
-
"https://github.com/python/cpython"
|
| 767 |
-
]
|
| 768 |
-
|
| 769 |
-
for repo in sample_repos:
|
| 770 |
-
if st.button(f"📦 {repo.split('/')[-1]}", key=repo):
|
| 771 |
-
st.session_state.github_url_input = repo
|
| 772 |
-
|
| 773 |
-
# Results Terminal
|
| 774 |
-
with col2:
|
| 775 |
-
st.markdown("### 📊 Analysis Results")
|
| 776 |
-
|
| 777 |
-
# Code Analysis Results
|
| 778 |
-
if analysis_mode == "Code Analysis":
|
| 779 |
-
if analyze_button:
|
| 780 |
-
if not code_input.strip():
|
| 781 |
-
st.error("🚨 Please enter some code to analyze or upload a file!")
|
| 782 |
-
else:
|
| 783 |
-
with st.spinner("🟢 Analyzing your code... Please wait..."):
|
| 784 |
-
if analyze_all:
|
| 785 |
-
# Multi-model analysis
|
| 786 |
-
st.markdown("#### 🔄 MULTI_NETWORK_ANALYSIS_INITIATED")
|
| 787 |
-
|
| 788 |
-
results = analyzer.analyze_with_all_models(
|
| 789 |
-
code_input,
|
| 790 |
-
selected_language if selected_language != "auto-detect" else None
|
| 791 |
-
)
|
| 792 |
-
|
| 793 |
-
# Display comparison metrics
|
| 794 |
-
comparison = analyzer.compare_analyses(results)
|
| 795 |
-
|
| 796 |
-
# Matrix-styled metrics
|
| 797 |
-
metrics_cols = st.columns(4)
|
| 798 |
-
with metrics_cols[0]:
|
| 799 |
-
st.metric("AVG_SCORE", f"{comparison['average_score']}/100")
|
| 800 |
-
with metrics_cols[1]:
|
| 801 |
-
st.metric("NETWORKS", len(results))
|
| 802 |
-
with metrics_cols[2]:
|
| 803 |
-
st.metric("PEAK_SCORE", f"{max(comparison['model_scores'].values())}/100")
|
| 804 |
-
with metrics_cols[3]:
|
| 805 |
-
st.metric("SCAN_TIME", f"{comparison['analysis_time']:.1f}s")
|
| 806 |
-
|
| 807 |
-
# Create tabs for each neural network
|
| 808 |
-
tab_names = [f"🤖 {available_models[key]}" for key in results.keys()]
|
| 809 |
-
tabs = st.tabs(tab_names)
|
| 810 |
-
|
| 811 |
-
for idx, (model_key, result) in enumerate(results.items()):
|
| 812 |
-
with tabs[idx]:
|
| 813 |
-
display_matrix_analysis_result(result, available_models[model_key])
|
| 814 |
-
|
| 815 |
-
# Consensus findings with Matrix styling
|
| 816 |
-
if comparison.get('consensus_bugs') or comparison.get('consensus_security'):
|
| 817 |
-
st.markdown("### 🤝 NEURAL_CONSENSUS_DETECTED")
|
| 818 |
-
st.markdown("""
|
| 819 |
-
<div style="background: rgba(255, 0, 0, 0.1); border: 2px solid #ff0000; padding: 15px; border-radius: 10px;">
|
| 820 |
-
<strong>CRITICAL_PATTERNS_IDENTIFIED_BY_MULTIPLE_NETWORKS:</strong>
|
| 821 |
-
</div>
|
| 822 |
-
""", unsafe_allow_html=True)
|
| 823 |
-
|
| 824 |
-
if comparison.get('consensus_bugs'):
|
| 825 |
-
st.markdown("#### 🐛 CONSENSUS_BUGS")
|
| 826 |
-
for bug in comparison['consensus_bugs']:
|
| 827 |
-
st.error(f"🚨 MULTIPLE_MODELS: {bug}")
|
| 828 |
-
|
| 829 |
-
if comparison.get('consensus_security'):
|
| 830 |
-
st.markdown("#### 🔒 CONSENSUS_SECURITY")
|
| 831 |
-
for vuln in comparison['consensus_security']:
|
| 832 |
-
st.error(f"🚨 SECURITY_ALERT: {vuln}")
|
| 833 |
-
|
| 834 |
-
else:
|
| 835 |
-
# Single model analysis
|
| 836 |
-
st.markdown(f"#### 🤖 {available_models[selected_model].upper()}_ANALYSIS")
|
| 837 |
-
|
| 838 |
-
result = analyzer.analyze_code(
|
| 839 |
-
code_input,
|
| 840 |
-
selected_model,
|
| 841 |
-
selected_language if selected_language != "auto-detect" else None
|
| 842 |
-
)
|
| 843 |
-
display_matrix_analysis_result(result, available_models[selected_model])
|
| 844 |
-
|
| 845 |
-
# GitHub Analysis Results
|
| 846 |
-
else: # GitHub Repository mode
|
| 847 |
-
if 'analyze_github_button' in locals() and analyze_github_button:
|
| 848 |
-
if not github_url.strip():
|
| 849 |
-
st.error("🚨 Please enter a GitHub repository URL!")
|
| 850 |
-
else:
|
| 851 |
-
with st.spinner("🟢 Analyzing GitHub repository... Please wait..."):
|
| 852 |
-
result = analyzer.analyze_github_repo(github_url, selected_model)
|
| 853 |
-
display_github_analysis_result(result, available_models[selected_model])
|
| 854 |
-
|
| 855 |
-
# Instructions for new users
|
| 856 |
-
if (analysis_mode == "Code Analysis" and not code_input.strip() and not analyze_button) or \
|
| 857 |
-
(analysis_mode == "GitHub Repository" and ('github_url' not in locals() or not github_url.strip()) and ('analyze_github_button' not in locals() or not analyze_github_button)):
|
| 858 |
-
|
| 859 |
-
st.markdown("""
|
| 860 |
-
<div class="matrix-terminal" style="margin: 20px 0; text-align: center;">
|
| 861 |
-
<h2 style="color: #00ff41; margin-bottom: 30px; font-size: 2.5rem;">
|
| 862 |
-
🤖 AI Code Analyzer
|
| 863 |
-
</h2>
|
| 864 |
-
<p style="color: #00ff41; font-size: 1.3rem; margin-bottom: 30px;">
|
| 865 |
-
<strong>What can I do for you?</strong>
|
| 866 |
-
</p>
|
| 867 |
-
</div>
|
| 868 |
-
""", unsafe_allow_html=True)
|
| 869 |
-
|
| 870 |
-
# Feature cards in columns
|
| 871 |
-
feature_col1, feature_col2 = st.columns(2)
|
| 872 |
-
|
| 873 |
-
with feature_col1:
|
| 874 |
-
st.markdown("""
|
| 875 |
-
<div style="background: linear-gradient(135deg, rgba(0,255,65,0.1), rgba(0,255,65,0.05));
|
| 876 |
-
border: 2px solid #00ff41; border-radius: 15px; padding: 25px; margin: 10px 0;
|
| 877 |
-
box-shadow: 0 0 20px rgba(0,255,65,0.3);">
|
| 878 |
-
<h3 style="color: #00ff41; margin-bottom: 15px;">🐛 Find Bugs Instantly</h3>
|
| 879 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6;">
|
| 880 |
-
Spot crashes, logical errors, and edge cases before they hit production.
|
| 881 |
-
</p>
|
| 882 |
-
</div>
|
| 883 |
-
""", unsafe_allow_html=True)
|
| 884 |
-
|
| 885 |
-
st.markdown("""
|
| 886 |
-
<div style="background: linear-gradient(135deg, rgba(0,255,65,0.1), rgba(0,255,65,0.05));
|
| 887 |
-
border: 2px solid #00ff41; border-radius: 15px; padding: 25px; margin: 10px 0;
|
| 888 |
-
box-shadow: 0 0 20px rgba(0,255,65,0.3);">
|
| 889 |
-
<h3 style="color: #00ff41; margin-bottom: 15px;">🔒 Security Scanner</h3>
|
| 890 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6;">
|
| 891 |
-
Detect vulnerabilities like SQL injection, XSS, and insecure data handling.
|
| 892 |
-
</p>
|
| 893 |
-
</div>
|
| 894 |
-
""", unsafe_allow_html=True)
|
| 895 |
-
|
| 896 |
-
with feature_col2:
|
| 897 |
-
st.markdown("""
|
| 898 |
-
<div style="background: linear-gradient(135deg, rgba(0,255,65,0.1), rgba(0,255,65,0.05));
|
| 899 |
-
border: 2px solid #00ff41; border-radius: 15px; padding: 25px; margin: 10px 0;
|
| 900 |
-
box-shadow: 0 0 20px rgba(0,255,65,0.3);">
|
| 901 |
-
<h3 style="color: #00ff41; margin-bottom: 15px;">📝 Code Quality Check</h3>
|
| 902 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6;">
|
| 903 |
-
Improve readability, maintainability, and follow best practices.
|
| 904 |
-
</p>
|
| 905 |
-
</div>
|
| 906 |
-
""", unsafe_allow_html=True)
|
| 907 |
-
|
| 908 |
-
st.markdown("""
|
| 909 |
-
<div style="background: linear-gradient(135deg, rgba(0,255,65,0.1), rgba(0,255,65,0.05));
|
| 910 |
-
border: 2px solid #00ff41; border-radius: 15px; padding: 25px; margin: 10px 0;
|
| 911 |
-
box-shadow: 0 0 20px rgba(0,255,65,0.3);">
|
| 912 |
-
<h3 style="color: #00ff41; margin-bottom: 15px;">📦 Repository Analysis</h3>
|
| 913 |
-
<p style="color: #ffffff; font-size: 16px; line-height: 1.6;">
|
| 914 |
-
Analyze entire GitHub repos for structure, issues, and improvements.
|
| 915 |
-
</p>
|
| 916 |
-
</div>
|
| 917 |
-
""", unsafe_allow_html=True)
|
| 918 |
-
|
| 919 |
-
# How to get started section
|
| 920 |
-
st.markdown("""
|
| 921 |
-
<div style="background: rgba(0,0,0,0.7); border: 1px solid #00ff41; border-radius: 10px;
|
| 922 |
-
padding: 20px; margin: 30px 0; text-align: center;">
|
| 923 |
-
<h3 style="color: #00ff41; margin-bottom: 20px;">🚀 Get Started in 3 Steps</h3>
|
| 924 |
-
<div style="display: flex; justify-content: space-around; flex-wrap: wrap;">
|
| 925 |
-
<div style="margin: 10px; color: #ffffff;">
|
| 926 |
-
<div style="background: #00ff41; color: #000; border-radius: 50%; width: 40px; height: 40px;
|
| 927 |
-
display: flex; align-items: center; justify-content: center; margin: 0 auto 10px;
|
| 928 |
-
font-weight: bold; font-size: 20px;">1</div>
|
| 929 |
-
<p><strong>Upload</strong><br>Paste code or GitHub URL</p>
|
| 930 |
-
</div>
|
| 931 |
-
<div style="margin: 10px; color: #ffffff;">
|
| 932 |
-
<div style="background: #00ff41; color: #000; border-radius: 50%; width: 40px; height: 40px;
|
| 933 |
-
display: flex; align-items: center; justify-content: center; margin: 0 auto 10px;
|
| 934 |
-
font-weight: bold; font-size: 20px;">2</div>
|
| 935 |
-
<p><strong>Choose AI</strong><br>Pick your preferred model</p>
|
| 936 |
-
</div>
|
| 937 |
-
<div style="margin: 10px; color: #ffffff;">
|
| 938 |
-
<div style="background: #00ff41; color: #000; border-radius: 50%; width: 40px; height: 40px;
|
| 939 |
-
display: flex; align-items: center; justify-content: center; margin: 0 auto 10px;
|
| 940 |
-
font-weight: bold; font-size: 20px;">3</div>
|
| 941 |
-
<p><strong>Analyze</strong><br>Get instant results</p>
|
| 942 |
-
</div>
|
| 943 |
-
</div>
|
| 944 |
-
</div>
|
| 945 |
-
""", unsafe_allow_html=True)
|
| 946 |
-
|
| 947 |
-
# Supported languages as badges
|
| 948 |
-
st.markdown("""
|
| 949 |
-
<div style="text-align: center; margin: 20px 0;">
|
| 950 |
-
<p style="color: #00ff41; font-size: 18px; margin-bottom: 15px;"><strong>Supported Languages:</strong></p>
|
| 951 |
-
<div style="display: flex; justify-content: center; flex-wrap: wrap; gap: 10px;">
|
| 952 |
-
<span style="background: linear-gradient(45deg, #00ff41, #00cc33); color: #000; padding: 8px 15px;
|
| 953 |
-
border-radius: 20px; font-weight: bold; font-size: 14px;">Python</span>
|
| 954 |
-
<span style="background: linear-gradient(45deg, #00ff41, #00cc33); color: #000; padding: 8px 15px;
|
| 955 |
-
border-radius: 20px; font-weight: bold; font-size: 14px;">JavaScript</span>
|
| 956 |
-
<span style="background: linear-gradient(45deg, #00ff41, #00cc33); color: #000; padding: 8px 15px;
|
| 957 |
-
border-radius: 20px; font-weight: bold; font-size: 14px;">Java</span>
|
| 958 |
-
<span style="background: linear-gradient(45deg, #00ff41, #00cc33); color: #000; padding: 8px 15px;
|
| 959 |
-
border-radius: 20px; font-weight: bold; font-size: 14px;">C++</span>
|
| 960 |
-
<span style="background: linear-gradient(45deg, #00ff41, #00cc33); color: #000; padding: 8px 15px;
|
| 961 |
-
border-radius: 20px; font-weight: bold; font-size: 14px;">Go</span>
|
| 962 |
-
<span style="background: linear-gradient(45deg, #00ff41, #00cc33); color: #000; padding: 8px 15px;
|
| 963 |
-
border-radius: 20px; font-weight: bold; font-size: 14px;">Rust</span>
|
| 964 |
-
<span style="background: linear-gradient(45deg, #00ff41, #00cc33); color: #000; padding: 8px 15px;
|
| 965 |
-
border-radius: 20px; font-weight: bold; font-size: 14px;">+ More</span>
|
| 966 |
-
</div>
|
| 967 |
-
</div>
|
| 968 |
-
""", unsafe_allow_html=True)
|
| 969 |
-
|
| 970 |
-
# Footer with Matrix signature
|
| 971 |
-
st.markdown("---")
|
| 972 |
-
st.markdown("""
|
| 973 |
-
<div style="text-align: center; color: #00ff41; font-family: 'Share Tech Mono', monospace; padding: 20px;">
|
| 974 |
-
<p>🟢 POWERED_BY_NEURAL_NETWORKS • OPENAI • ANTHROPIC • DEEPSEEK • GOOGLE 🟢</p>
|
| 975 |
-
<p><em>"There is no spoon... only code to analyze."</em></p>
|
| 976 |
-
<p style="font-size: 12px;">MATRIX_ANALYZER_v3.0 • BUILD_2024 • SECURITY_CLEARANCE_OMEGA • FILE_UPLOAD_ENABLED</p>
|
| 977 |
-
</div>
|
| 978 |
-
""", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model_comparison.py
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Model Comparison Script for AI Code Analyzer
|
| 4 |
+
|
| 5 |
+
This script helps you compare different code analysis models
|
| 6 |
+
and understand their capabilities before fine-tuning.
|
| 7 |
+
|
| 8 |
+
Author: AI Code Analyzer Project
|
| 9 |
+
Date: 2025
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import torch
|
| 13 |
+
from transformers import (
|
| 14 |
+
AutoModelForCausalLM,
|
| 15 |
+
AutoModelForSeq2SeqLM,
|
| 16 |
+
AutoTokenizer,
|
| 17 |
+
BitsAndBytesConfig
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
def compare_models():
|
| 21 |
+
"""
|
| 22 |
+
Compare different code analysis models available on Hugging Face.
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
models_to_compare = {
|
| 26 |
+
"Current Model (GPT-2)": {
|
| 27 |
+
"model_id": "gpt2",
|
| 28 |
+
"type": "CausalLM",
|
| 29 |
+
"size": "124M",
|
| 30 |
+
"code_specialized": False,
|
| 31 |
+
"description": "General-purpose text model, not optimized for code"
|
| 32 |
+
},
|
| 33 |
+
"CodeT5+ (Recommended)": {
|
| 34 |
+
"model_id": "Salesforce/codet5p-220m",
|
| 35 |
+
"type": "Seq2SeqLM",
|
| 36 |
+
"size": "220M",
|
| 37 |
+
"code_specialized": True,
|
| 38 |
+
"description": "Specialized for code understanding and generation"
|
| 39 |
+
},
|
| 40 |
+
"CodeBERT": {
|
| 41 |
+
"model_id": "microsoft/CodeBERT-base",
|
| 42 |
+
"type": "FeatureExtraction",
|
| 43 |
+
"size": "125M",
|
| 44 |
+
"code_specialized": True,
|
| 45 |
+
"description": "Pre-trained on code for understanding programming languages"
|
| 46 |
+
},
|
| 47 |
+
"GraphCodeBERT": {
|
| 48 |
+
"model_id": "microsoft/GraphCodeBERT-base",
|
| 49 |
+
"type": "FeatureExtraction",
|
| 50 |
+
"size": "125M",
|
| 51 |
+
"code_specialized": True,
|
| 52 |
+
"description": "Understands code structure and dependencies"
|
| 53 |
+
},
|
| 54 |
+
"InCoder": {
|
| 55 |
+
"model_id": "facebook/incoder-1B",
|
| 56 |
+
"type": "CausalLM",
|
| 57 |
+
"size": "1B",
|
| 58 |
+
"code_specialized": True,
|
| 59 |
+
"description": "Code completion and analysis with large context"
|
| 60 |
+
}
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
print("🤖 Code Analysis Models Comparison")
|
| 64 |
+
print("=" * 80)
|
| 65 |
+
|
| 66 |
+
for name, info in models_to_compare.items():
|
| 67 |
+
print(f"\n📊 {name}")
|
| 68 |
+
print(f" Model ID: {info['model_id']}")
|
| 69 |
+
print(f" Type: {info['type']}")
|
| 70 |
+
print(f" Size: {info['size']}")
|
| 71 |
+
print(f" Code Specialized: {'✅ Yes' if info['code_specialized'] else '❌ No'}")
|
| 72 |
+
print(f" Description: {info['description']}")
|
| 73 |
+
|
| 74 |
+
print("\n" + "=" * 80)
|
| 75 |
+
print("🎯 RECOMMENDATIONS:")
|
| 76 |
+
print("=" * 80)
|
| 77 |
+
|
| 78 |
+
print("\n🥇 BEST CHOICE: Salesforce/codet5p-220m")
|
| 79 |
+
print(" ✅ Specialized for code analysis")
|
| 80 |
+
print(" ✅ Good balance of size and performance")
|
| 81 |
+
print(" ✅ Works well with your training data format")
|
| 82 |
+
print(" ✅ Seq2Seq architecture perfect for code analysis")
|
| 83 |
+
|
| 84 |
+
print("\n🥈 ALTERNATIVE: facebook/incoder-1B")
|
| 85 |
+
print(" ✅ Excellent code understanding")
|
| 86 |
+
print(" ✅ Large context window")
|
| 87 |
+
print(" ⚠️ Larger model (requires more resources)")
|
| 88 |
+
|
| 89 |
+
print("\n🥉 FOR EXPERIMENTATION: microsoft/CodeBERT-base")
|
| 90 |
+
print(" ✅ Proven for code understanding")
|
| 91 |
+
print(" ✅ Good for feature extraction")
|
| 92 |
+
print(" ⚠️ Different architecture (might need data format changes)")
|
| 93 |
+
|
| 94 |
+
def test_model_loading(model_id: str, model_type: str = "auto"):
|
| 95 |
+
"""
|
| 96 |
+
Test loading a specific model to ensure it works.
|
| 97 |
+
|
| 98 |
+
Args:
|
| 99 |
+
model_id (str): Hugging Face model ID
|
| 100 |
+
model_type (str): Model type ("auto", "causal", "seq2seq")
|
| 101 |
+
"""
|
| 102 |
+
print(f"\n🧪 Testing model: {model_id}")
|
| 103 |
+
print("-" * 50)
|
| 104 |
+
|
| 105 |
+
try:
|
| 106 |
+
# Load tokenizer
|
| 107 |
+
print("Loading tokenizer...")
|
| 108 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 109 |
+
|
| 110 |
+
if tokenizer.pad_token is None:
|
| 111 |
+
tokenizer.pad_token = tokenizer.eos_token
|
| 112 |
+
print("✅ Added padding token")
|
| 113 |
+
|
| 114 |
+
# Load model
|
| 115 |
+
print("Loading model...")
|
| 116 |
+
if model_type == "seq2seq" or "codet5" in model_id.lower():
|
| 117 |
+
model = AutoModelForSeq2SeqLM.from_pretrained(model_id)
|
| 118 |
+
else:
|
| 119 |
+
model = AutoModelForCausalLM.from_pretrained(model_id)
|
| 120 |
+
|
| 121 |
+
print(f"✅ Model loaded successfully!")
|
| 122 |
+
print(f" Model type: {type(model).__name__}")
|
| 123 |
+
print(f" Parameters: {sum(p.numel() for p in model.parameters()):,}")
|
| 124 |
+
|
| 125 |
+
# Test with a simple code snippet
|
| 126 |
+
test_code = "def add(a, b):\n return a + b"
|
| 127 |
+
inputs = tokenizer(test_code, return_tensors="pt", truncation=True, max_length=512)
|
| 128 |
+
|
| 129 |
+
print(f"✅ Tokenization test passed")
|
| 130 |
+
print(f" Input tokens: {inputs['input_ids'].shape[1]}")
|
| 131 |
+
|
| 132 |
+
return True
|
| 133 |
+
|
| 134 |
+
except Exception as e:
|
| 135 |
+
print(f"❌ Error loading model: {str(e)}")
|
| 136 |
+
return False
|
| 137 |
+
|
| 138 |
+
def main():
|
| 139 |
+
"""
|
| 140 |
+
Main function to run model comparison and testing.
|
| 141 |
+
"""
|
| 142 |
+
print("🚀 AI Code Analyzer - Model Comparison Tool")
|
| 143 |
+
print("=" * 80)
|
| 144 |
+
|
| 145 |
+
# Show comparison
|
| 146 |
+
compare_models()
|
| 147 |
+
|
| 148 |
+
# Test recommended models
|
| 149 |
+
print("\n\n🧪 TESTING RECOMMENDED MODELS:")
|
| 150 |
+
print("=" * 80)
|
| 151 |
+
|
| 152 |
+
models_to_test = [
|
| 153 |
+
("Salesforce/codet5p-220m", "seq2seq"),
|
| 154 |
+
("microsoft/CodeBERT-base", "causal"),
|
| 155 |
+
("facebook/incoder-1B", "causal")
|
| 156 |
+
]
|
| 157 |
+
|
| 158 |
+
working_models = []
|
| 159 |
+
|
| 160 |
+
for model_id, model_type in models_to_test:
|
| 161 |
+
if test_model_loading(model_id, model_type):
|
| 162 |
+
working_models.append(model_id)
|
| 163 |
+
|
| 164 |
+
print(f"\n🎉 SUCCESS: {len(working_models)} models loaded successfully!")
|
| 165 |
+
|
| 166 |
+
if working_models:
|
| 167 |
+
print("\n📋 NEXT STEPS:")
|
| 168 |
+
print("1. Choose your preferred model from the working models above")
|
| 169 |
+
print("2. Run: python finetune_improved.py --model <model_id> --dry-run")
|
| 170 |
+
print("3. Test the fine-tuned model with your code analyzer")
|
| 171 |
+
print("\n💡 RECOMMENDED COMMAND:")
|
| 172 |
+
print(f" python finetune_improved.py --model {working_models[0]} --dry-run")
|
| 173 |
+
|
| 174 |
+
if __name__ == "__main__":
|
| 175 |
+
main()
|
netlify.toml
DELETED
|
@@ -1,9 +0,0 @@
|
|
| 1 |
-
[build]
|
| 2 |
-
command = "echo 'This is a Python Streamlit app - deploy to Render, Railway, or Heroku instead'"
|
| 3 |
-
publish = "."
|
| 4 |
-
|
| 5 |
-
[[redirects]]
|
| 6 |
-
from = "/*"
|
| 7 |
-
to = "https://your-app-name.onrender.com/:splat"
|
| 8 |
-
status = 301
|
| 9 |
-
force = true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
optimized_code_analyzer.py
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Optimized CodeT5+ Code Analyzer
|
| 4 |
+
|
| 5 |
+
This script implements CodeT5+ with multiple speed optimizations:
|
| 6 |
+
- FP16 by default (fastest on your GPU); optional INT8/INT4
|
| 7 |
+
- Response streaming for better UX
|
| 8 |
+
- Progress indicators
|
| 9 |
+
- Result caching
|
| 10 |
+
- Optimized generation parameters
|
| 11 |
+
|
| 12 |
+
Author: AI Code Analyzer Project
|
| 13 |
+
Date: 2025
|
| 14 |
+
"""
|
| 15 |
+
|
| 16 |
+
import torch
|
| 17 |
+
import time
|
| 18 |
+
import hashlib
|
| 19 |
+
import json
|
| 20 |
+
import os
|
| 21 |
+
from typing import Dict, Any, Optional, Generator
|
| 22 |
+
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, BitsAndBytesConfig
|
| 23 |
+
from tqdm import tqdm
|
| 24 |
+
import streamlit as st
|
| 25 |
+
|
| 26 |
+
class OptimizedCodeAnalyzer:
|
| 27 |
+
"""
|
| 28 |
+
Optimized CodeT5+ analyzer with speed improvements.
|
| 29 |
+
"""
|
| 30 |
+
|
| 31 |
+
def __init__(
|
| 32 |
+
self,
|
| 33 |
+
model_id: str = "Salesforce/codet5p-220m",
|
| 34 |
+
cache_dir: str = "./cache",
|
| 35 |
+
precision: str = "fp16", # one of: fp16 | int8 | int4
|
| 36 |
+
quick_max_new_tokens: int = 180,
|
| 37 |
+
detailed_max_new_tokens: int = 240,
|
| 38 |
+
):
|
| 39 |
+
"""
|
| 40 |
+
Initialize the optimized analyzer.
|
| 41 |
+
|
| 42 |
+
Args:
|
| 43 |
+
model_id: Hugging Face model ID
|
| 44 |
+
cache_dir: Directory to store cached results
|
| 45 |
+
"""
|
| 46 |
+
self.model_id = model_id
|
| 47 |
+
self.cache_dir = cache_dir
|
| 48 |
+
self.model = None
|
| 49 |
+
self.tokenizer = None
|
| 50 |
+
self.cache = {}
|
| 51 |
+
self.precision = precision.lower().strip()
|
| 52 |
+
self.quick_max_new_tokens = quick_max_new_tokens
|
| 53 |
+
self.detailed_max_new_tokens = detailed_max_new_tokens
|
| 54 |
+
|
| 55 |
+
# Create cache directory
|
| 56 |
+
os.makedirs(cache_dir, exist_ok=True)
|
| 57 |
+
|
| 58 |
+
# Load cache if exists
|
| 59 |
+
self._load_cache()
|
| 60 |
+
|
| 61 |
+
def _create_quantization_config(self) -> BitsAndBytesConfig:
|
| 62 |
+
"""
|
| 63 |
+
Create 4-bit quantization configuration for faster inference.
|
| 64 |
+
|
| 65 |
+
Returns:
|
| 66 |
+
BitsAndBytesConfig: Quantization configuration
|
| 67 |
+
"""
|
| 68 |
+
# Default to INT4 nf4 when precision==int4; callers should not use this
|
| 69 |
+
return BitsAndBytesConfig(
|
| 70 |
+
load_in_4bit=True,
|
| 71 |
+
bnb_4bit_quant_type="nf4",
|
| 72 |
+
bnb_4bit_compute_dtype=torch.float16,
|
| 73 |
+
bnb_4bit_use_double_quant=True,
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
def _load_model(self):
|
| 77 |
+
"""
|
| 78 |
+
Load the model with optimizations.
|
| 79 |
+
"""
|
| 80 |
+
if self.model is not None:
|
| 81 |
+
return
|
| 82 |
+
|
| 83 |
+
print("🚀 Loading optimized CodeT5+ model...")
|
| 84 |
+
|
| 85 |
+
# Load tokenizer
|
| 86 |
+
self.tokenizer = AutoTokenizer.from_pretrained(self.model_id)
|
| 87 |
+
if self.tokenizer.pad_token is None:
|
| 88 |
+
self.tokenizer.pad_token = self.tokenizer.eos_token
|
| 89 |
+
|
| 90 |
+
# Decide precision based on config
|
| 91 |
+
quantization_config = None
|
| 92 |
+
dtype = None
|
| 93 |
+
banner = ""
|
| 94 |
+
|
| 95 |
+
if self.precision == "fp16":
|
| 96 |
+
dtype = torch.float16
|
| 97 |
+
banner = "FP16 precision"
|
| 98 |
+
elif self.precision == "int8":
|
| 99 |
+
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
|
| 100 |
+
banner = "INT8 quantization"
|
| 101 |
+
elif self.precision == "int4":
|
| 102 |
+
quantization_config = self._create_quantization_config()
|
| 103 |
+
banner = "INT4 (nf4) quantization"
|
| 104 |
+
else:
|
| 105 |
+
# Fallback to fp16
|
| 106 |
+
dtype = torch.float16
|
| 107 |
+
banner = f"Unknown precision '{self.precision}', defaulting to FP16"
|
| 108 |
+
|
| 109 |
+
self.model = AutoModelForSeq2SeqLM.from_pretrained(
|
| 110 |
+
self.model_id,
|
| 111 |
+
device_map="auto",
|
| 112 |
+
dtype=dtype,
|
| 113 |
+
quantization_config=quantization_config,
|
| 114 |
+
)
|
| 115 |
+
|
| 116 |
+
print(f"✅ Model loaded with {banner}!")
|
| 117 |
+
|
| 118 |
+
def _get_cache_key(self, code: str) -> str:
|
| 119 |
+
"""
|
| 120 |
+
Generate cache key for code.
|
| 121 |
+
|
| 122 |
+
Args:
|
| 123 |
+
code: Code to analyze
|
| 124 |
+
|
| 125 |
+
Returns:
|
| 126 |
+
str: Cache key
|
| 127 |
+
"""
|
| 128 |
+
return hashlib.md5(code.encode()).hexdigest()
|
| 129 |
+
|
| 130 |
+
def _load_cache(self):
|
| 131 |
+
"""
|
| 132 |
+
Load cached results from disk.
|
| 133 |
+
"""
|
| 134 |
+
cache_file = os.path.join(self.cache_dir, "analysis_cache.json")
|
| 135 |
+
if os.path.exists(cache_file):
|
| 136 |
+
try:
|
| 137 |
+
with open(cache_file, 'r') as f:
|
| 138 |
+
self.cache = json.load(f)
|
| 139 |
+
print(f"📁 Loaded {len(self.cache)} cached analyses")
|
| 140 |
+
except:
|
| 141 |
+
self.cache = {}
|
| 142 |
+
|
| 143 |
+
def _save_cache(self):
|
| 144 |
+
"""
|
| 145 |
+
Save cache to disk.
|
| 146 |
+
"""
|
| 147 |
+
cache_file = os.path.join(self.cache_dir, "analysis_cache.json")
|
| 148 |
+
with open(cache_file, 'w') as f:
|
| 149 |
+
json.dump(self.cache, f)
|
| 150 |
+
|
| 151 |
+
def _check_cache(self, code: str) -> Optional[Dict[str, Any]]:
|
| 152 |
+
"""
|
| 153 |
+
Check if analysis is cached.
|
| 154 |
+
|
| 155 |
+
Args:
|
| 156 |
+
code: Code to analyze
|
| 157 |
+
|
| 158 |
+
Returns:
|
| 159 |
+
Optional[Dict]: Cached result or None
|
| 160 |
+
"""
|
| 161 |
+
cache_key = self._get_cache_key(code)
|
| 162 |
+
return self.cache.get(cache_key)
|
| 163 |
+
|
| 164 |
+
def _save_to_cache(self, code: str, result: Dict[str, Any]):
|
| 165 |
+
"""
|
| 166 |
+
Save analysis result to cache.
|
| 167 |
+
|
| 168 |
+
Args:
|
| 169 |
+
code: Code that was analyzed
|
| 170 |
+
result: Analysis result
|
| 171 |
+
"""
|
| 172 |
+
cache_key = self._get_cache_key(code)
|
| 173 |
+
self.cache[cache_key] = result
|
| 174 |
+
self._save_cache()
|
| 175 |
+
|
| 176 |
+
def analyze_code_streaming(
|
| 177 |
+
self,
|
| 178 |
+
code: str,
|
| 179 |
+
show_progress: bool = True,
|
| 180 |
+
mode: str = "detailed", # "quick" | "detailed"
|
| 181 |
+
) -> Generator[str, None, Dict[str, Any]]:
|
| 182 |
+
"""
|
| 183 |
+
Analyze code with streaming response and progress indicators.
|
| 184 |
+
|
| 185 |
+
Args:
|
| 186 |
+
code: Code to analyze
|
| 187 |
+
show_progress: Whether to show progress indicators
|
| 188 |
+
|
| 189 |
+
Yields:
|
| 190 |
+
str: Partial analysis results
|
| 191 |
+
"""
|
| 192 |
+
# Check cache first
|
| 193 |
+
cached_result = self._check_cache(code)
|
| 194 |
+
if cached_result:
|
| 195 |
+
print("⚡ Using cached result!")
|
| 196 |
+
yield cached_result["analysis"]
|
| 197 |
+
return cached_result
|
| 198 |
+
|
| 199 |
+
# Load model if not loaded
|
| 200 |
+
self._load_model()
|
| 201 |
+
|
| 202 |
+
# Create analysis prompt
|
| 203 |
+
prompt = f"""Analyze this code for bugs, performance issues, and security concerns:
|
| 204 |
+
|
| 205 |
+
{code}
|
| 206 |
+
|
| 207 |
+
Analysis:"""
|
| 208 |
+
|
| 209 |
+
# Tokenize input
|
| 210 |
+
inputs = self.tokenizer(
|
| 211 |
+
prompt,
|
| 212 |
+
return_tensors="pt",
|
| 213 |
+
truncation=True,
|
| 214 |
+
max_length=512,
|
| 215 |
+
padding=True,
|
| 216 |
+
)
|
| 217 |
+
device = next(self.model.parameters()).device
|
| 218 |
+
inputs = {k: v.to(device) for k, v in inputs.items()}
|
| 219 |
+
|
| 220 |
+
# Generate analysis with optimized parameters
|
| 221 |
+
start_time = time.time()
|
| 222 |
+
|
| 223 |
+
if show_progress:
|
| 224 |
+
print("🔍 Analyzing code...")
|
| 225 |
+
progress_bar = tqdm(total=100, desc="Analysis Progress")
|
| 226 |
+
|
| 227 |
+
try:
|
| 228 |
+
with torch.no_grad():
|
| 229 |
+
# Use optimized generation parameters for speed
|
| 230 |
+
max_new = self.detailed_max_new_tokens if mode == "detailed" else self.quick_max_new_tokens
|
| 231 |
+
num_beams = 2 if mode == "detailed" else 1
|
| 232 |
+
outputs = self.model.generate(
|
| 233 |
+
inputs["input_ids"],
|
| 234 |
+
attention_mask=inputs.get("attention_mask"),
|
| 235 |
+
max_new_tokens=max_new,
|
| 236 |
+
num_beams=num_beams,
|
| 237 |
+
do_sample=False,
|
| 238 |
+
pad_token_id=self.tokenizer.eos_token_id,
|
| 239 |
+
use_cache=True,
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
if show_progress:
|
| 243 |
+
progress_bar.update(50)
|
| 244 |
+
|
| 245 |
+
# Decode analysis
|
| 246 |
+
analysis = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 247 |
+
analysis_text = analysis[len(prompt):].strip()
|
| 248 |
+
|
| 249 |
+
if show_progress:
|
| 250 |
+
progress_bar.update(50)
|
| 251 |
+
progress_bar.close()
|
| 252 |
+
|
| 253 |
+
# Calculate quality score
|
| 254 |
+
quality_score = self._calculate_quality_score(analysis_text)
|
| 255 |
+
|
| 256 |
+
total_time = time.time() - start_time
|
| 257 |
+
|
| 258 |
+
# Create result
|
| 259 |
+
result = {
|
| 260 |
+
"analysis": analysis_text,
|
| 261 |
+
"quality_score": quality_score,
|
| 262 |
+
"execution_time": total_time,
|
| 263 |
+
"model": self.model_id,
|
| 264 |
+
"cached": False
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
# Save to cache
|
| 268 |
+
self._save_to_cache(code, result)
|
| 269 |
+
|
| 270 |
+
# Yield the analysis
|
| 271 |
+
yield analysis_text
|
| 272 |
+
|
| 273 |
+
return result
|
| 274 |
+
|
| 275 |
+
except Exception as e:
|
| 276 |
+
if show_progress:
|
| 277 |
+
progress_bar.close()
|
| 278 |
+
raise e
|
| 279 |
+
|
| 280 |
+
def analyze_code_fast(self, code: str, mode: str = "quick") -> Dict[str, Any]:
|
| 281 |
+
"""
|
| 282 |
+
Fast analysis without streaming (for batch processing).
|
| 283 |
+
|
| 284 |
+
Args:
|
| 285 |
+
code: Code to analyze
|
| 286 |
+
|
| 287 |
+
Returns:
|
| 288 |
+
Dict: Analysis result
|
| 289 |
+
"""
|
| 290 |
+
# Check cache first
|
| 291 |
+
cached_result = self._check_cache(code)
|
| 292 |
+
if cached_result:
|
| 293 |
+
cached_result["cached"] = True
|
| 294 |
+
return cached_result
|
| 295 |
+
|
| 296 |
+
# Load model if not loaded
|
| 297 |
+
self._load_model()
|
| 298 |
+
|
| 299 |
+
# Create analysis prompt
|
| 300 |
+
prompt = f"""Analyze this code for bugs, performance issues, and security concerns:
|
| 301 |
+
|
| 302 |
+
{code}
|
| 303 |
+
|
| 304 |
+
Analysis:"""
|
| 305 |
+
|
| 306 |
+
# Tokenize input
|
| 307 |
+
inputs = self.tokenizer(
|
| 308 |
+
prompt,
|
| 309 |
+
return_tensors="pt",
|
| 310 |
+
truncation=True,
|
| 311 |
+
max_length=512,
|
| 312 |
+
padding=True,
|
| 313 |
+
)
|
| 314 |
+
device = next(self.model.parameters()).device
|
| 315 |
+
inputs = {k: v.to(device) for k, v in inputs.items()}
|
| 316 |
+
|
| 317 |
+
# Generate analysis with speed optimizations
|
| 318 |
+
start_time = time.time()
|
| 319 |
+
|
| 320 |
+
with torch.no_grad():
|
| 321 |
+
max_new = self.quick_max_new_tokens if mode == "quick" else self.detailed_max_new_tokens
|
| 322 |
+
num_beams = 1 if mode == "quick" else 2
|
| 323 |
+
outputs = self.model.generate(
|
| 324 |
+
inputs["input_ids"],
|
| 325 |
+
attention_mask=inputs.get("attention_mask"),
|
| 326 |
+
max_new_tokens=max_new,
|
| 327 |
+
num_beams=num_beams,
|
| 328 |
+
do_sample=False,
|
| 329 |
+
pad_token_id=self.tokenizer.eos_token_id,
|
| 330 |
+
use_cache=True,
|
| 331 |
+
)
|
| 332 |
+
|
| 333 |
+
# Decode analysis
|
| 334 |
+
analysis = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 335 |
+
analysis_text = analysis[len(prompt):].strip()
|
| 336 |
+
|
| 337 |
+
# Calculate quality score
|
| 338 |
+
quality_score = self._calculate_quality_score(analysis_text)
|
| 339 |
+
|
| 340 |
+
total_time = time.time() - start_time
|
| 341 |
+
|
| 342 |
+
# Create result
|
| 343 |
+
result = {
|
| 344 |
+
"analysis": analysis_text,
|
| 345 |
+
"quality_score": quality_score,
|
| 346 |
+
"execution_time": total_time,
|
| 347 |
+
"model": self.model_id,
|
| 348 |
+
"cached": False
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
# Save to cache
|
| 352 |
+
self._save_to_cache(code, result)
|
| 353 |
+
|
| 354 |
+
return result
|
| 355 |
+
|
| 356 |
+
def _calculate_quality_score(self, analysis_text: str) -> int:
|
| 357 |
+
"""
|
| 358 |
+
Calculate quality score for analysis.
|
| 359 |
+
|
| 360 |
+
Args:
|
| 361 |
+
analysis_text: Analysis text
|
| 362 |
+
|
| 363 |
+
Returns:
|
| 364 |
+
int: Quality score (0-100)
|
| 365 |
+
"""
|
| 366 |
+
score = 0
|
| 367 |
+
analysis_lower = analysis_text.lower()
|
| 368 |
+
|
| 369 |
+
# Check for different types of analysis (20 points each)
|
| 370 |
+
if any(word in analysis_lower for word in ['bug', 'error', 'issue', 'problem', 'flaw']):
|
| 371 |
+
score += 20
|
| 372 |
+
|
| 373 |
+
if any(word in analysis_lower for word in ['performance', 'slow', 'efficient', 'complexity', 'optimization']):
|
| 374 |
+
score += 20
|
| 375 |
+
|
| 376 |
+
if any(word in analysis_lower for word in ['security', 'vulnerability', 'safe', 'unsafe', 'risk']):
|
| 377 |
+
score += 20
|
| 378 |
+
|
| 379 |
+
if any(word in analysis_lower for word in ['suggest', 'improve', 'better', 'recommend', 'fix', 'solution']):
|
| 380 |
+
score += 20
|
| 381 |
+
|
| 382 |
+
# Bonus for detailed analysis
|
| 383 |
+
if len(analysis_text) > 200:
|
| 384 |
+
score += 10
|
| 385 |
+
if len(analysis_text) > 500:
|
| 386 |
+
score += 10
|
| 387 |
+
|
| 388 |
+
return min(score, 100)
|
| 389 |
+
|
| 390 |
+
def get_model_info(self) -> Dict[str, Any]:
|
| 391 |
+
"""
|
| 392 |
+
Get information about the loaded model.
|
| 393 |
+
|
| 394 |
+
Returns:
|
| 395 |
+
Dict: Model information
|
| 396 |
+
"""
|
| 397 |
+
if self.model is None:
|
| 398 |
+
return {"status": "Model not loaded"}
|
| 399 |
+
|
| 400 |
+
param_count = sum(p.numel() for p in self.model.parameters())
|
| 401 |
+
device = next(self.model.parameters()).device
|
| 402 |
+
|
| 403 |
+
return {
|
| 404 |
+
"model_id": self.model_id,
|
| 405 |
+
"parameters": param_count,
|
| 406 |
+
"device": str(device),
|
| 407 |
+
"precision": self.precision,
|
| 408 |
+
"quick_max_new_tokens": self.quick_max_new_tokens,
|
| 409 |
+
"detailed_max_new_tokens": self.detailed_max_new_tokens,
|
| 410 |
+
"cache_size": len(self.cache)
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
def main():
|
| 414 |
+
"""
|
| 415 |
+
Demo of the optimized analyzer.
|
| 416 |
+
"""
|
| 417 |
+
print("🚀 Optimized CodeT5+ Analyzer Demo")
|
| 418 |
+
print("=" * 60)
|
| 419 |
+
|
| 420 |
+
# Initialize analyzer
|
| 421 |
+
analyzer = OptimizedCodeAnalyzer()
|
| 422 |
+
|
| 423 |
+
# Test code
|
| 424 |
+
test_code = """
|
| 425 |
+
def calculate_fibonacci(n):
|
| 426 |
+
if n <= 0:
|
| 427 |
+
return 0
|
| 428 |
+
elif n == 1:
|
| 429 |
+
return 1
|
| 430 |
+
else:
|
| 431 |
+
return calculate_fibonacci(n-1) + calculate_fibonacci(n-2)
|
| 432 |
+
|
| 433 |
+
# This will be slow for large numbers
|
| 434 |
+
result = calculate_fibonacci(35)
|
| 435 |
+
print(result)
|
| 436 |
+
"""
|
| 437 |
+
|
| 438 |
+
print(f"Test Code:\n{test_code}")
|
| 439 |
+
print("=" * 60)
|
| 440 |
+
|
| 441 |
+
# Test streaming analysis
|
| 442 |
+
print("\n🔍 Streaming Analysis:")
|
| 443 |
+
print("-" * 40)
|
| 444 |
+
|
| 445 |
+
for partial_result in analyzer.analyze_code_streaming(test_code):
|
| 446 |
+
print(partial_result)
|
| 447 |
+
|
| 448 |
+
# Test fast analysis
|
| 449 |
+
print("\n⚡ Fast Analysis:")
|
| 450 |
+
print("-" * 40)
|
| 451 |
+
|
| 452 |
+
result = analyzer.analyze_code_fast(test_code)
|
| 453 |
+
print(f"Analysis: {result['analysis']}")
|
| 454 |
+
print(f"Quality Score: {result['quality_score']}/100")
|
| 455 |
+
print(f"Execution Time: {result['execution_time']:.2f}s")
|
| 456 |
+
print(f"Cached: {result['cached']}")
|
| 457 |
+
|
| 458 |
+
# Show model info
|
| 459 |
+
print("\n📊 Model Information:")
|
| 460 |
+
print("-" * 40)
|
| 461 |
+
model_info = analyzer.get_model_info()
|
| 462 |
+
for key, value in model_info.items():
|
| 463 |
+
print(f"{key}: {value}")
|
| 464 |
+
|
| 465 |
+
if __name__ == "__main__":
|
| 466 |
+
main()
|
optimized_code_analyzer_enhanced.py
ADDED
|
@@ -0,0 +1,542 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Enhanced Code Analyzer with Fine-tuned Model Support
|
| 4 |
+
|
| 5 |
+
This version supports:
|
| 6 |
+
- Base CodeT5+ model (original)
|
| 7 |
+
- Fine-tuned DeepSeek Coder model (new)
|
| 8 |
+
- Easy toggle between models
|
| 9 |
+
- All existing optimizations (caching, streaming, etc.)
|
| 10 |
+
|
| 11 |
+
Author: AI Code Analyzer Project
|
| 12 |
+
Date: 2025
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
import torch
|
| 16 |
+
import time
|
| 17 |
+
import hashlib
|
| 18 |
+
import json
|
| 19 |
+
import os
|
| 20 |
+
from typing import Dict, Any, Optional, Generator, Literal
|
| 21 |
+
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, AutoModelForCausalLM, BitsAndBytesConfig
|
| 22 |
+
from peft import PeftModel
|
| 23 |
+
from tqdm import tqdm
|
| 24 |
+
import streamlit as st
|
| 25 |
+
|
| 26 |
+
ModelType = Literal["codet5", "deepseek-finetuned"]
|
| 27 |
+
|
| 28 |
+
class EnhancedCodeAnalyzer:
|
| 29 |
+
"""
|
| 30 |
+
Enhanced analyzer supporting multiple model types including fine-tuned models.
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
def __init__(
|
| 34 |
+
self,
|
| 35 |
+
model_type: ModelType = "codet5",
|
| 36 |
+
model_id: Optional[str] = None,
|
| 37 |
+
adapter_path: Optional[str] = None,
|
| 38 |
+
cache_dir: str = "./cache",
|
| 39 |
+
precision: str = "fp16",
|
| 40 |
+
quick_max_new_tokens: int = 180,
|
| 41 |
+
detailed_max_new_tokens: int = 300,
|
| 42 |
+
):
|
| 43 |
+
"""
|
| 44 |
+
Initialize the enhanced analyzer.
|
| 45 |
+
|
| 46 |
+
Args:
|
| 47 |
+
model_type: Type of model to use ("codet5" or "deepseek-finetuned")
|
| 48 |
+
model_id: Hugging Face model ID (auto-selected if None)
|
| 49 |
+
adapter_path: Path to LoRA adapters for fine-tuned models
|
| 50 |
+
cache_dir: Directory to store cached results
|
| 51 |
+
precision: Model precision (fp16, int8, int4)
|
| 52 |
+
quick_max_new_tokens: Max tokens for quick analysis
|
| 53 |
+
detailed_max_new_tokens: Max tokens for detailed analysis
|
| 54 |
+
"""
|
| 55 |
+
self.model_type = model_type
|
| 56 |
+
self.cache_dir = cache_dir
|
| 57 |
+
self.precision = precision.lower().strip()
|
| 58 |
+
self.quick_max_new_tokens = quick_max_new_tokens
|
| 59 |
+
self.detailed_max_new_tokens = detailed_max_new_tokens
|
| 60 |
+
|
| 61 |
+
# Auto-select model_id based on type
|
| 62 |
+
if model_id is None:
|
| 63 |
+
if model_type == "codet5":
|
| 64 |
+
self.model_id = "Salesforce/codet5p-220m"
|
| 65 |
+
elif model_type == "deepseek-finetuned":
|
| 66 |
+
self.model_id = "deepseek-ai/deepseek-coder-1.3b-instruct"
|
| 67 |
+
else:
|
| 68 |
+
raise ValueError(f"Unknown model_type: {model_type}")
|
| 69 |
+
else:
|
| 70 |
+
self.model_id = model_id
|
| 71 |
+
|
| 72 |
+
# Set adapter path
|
| 73 |
+
self.adapter_path = adapter_path
|
| 74 |
+
if model_type == "deepseek-finetuned" and adapter_path is None:
|
| 75 |
+
self.adapter_path = "./fine-tuned-analyst"
|
| 76 |
+
|
| 77 |
+
self.model = None
|
| 78 |
+
self.tokenizer = None
|
| 79 |
+
self.cache = {}
|
| 80 |
+
|
| 81 |
+
# Create cache directory
|
| 82 |
+
os.makedirs(cache_dir, exist_ok=True)
|
| 83 |
+
|
| 84 |
+
# Load cache if exists
|
| 85 |
+
self._load_cache()
|
| 86 |
+
|
| 87 |
+
def _create_quantization_config(self) -> BitsAndBytesConfig:
|
| 88 |
+
"""Create quantization configuration."""
|
| 89 |
+
return BitsAndBytesConfig(
|
| 90 |
+
load_in_4bit=True,
|
| 91 |
+
bnb_4bit_quant_type="nf4",
|
| 92 |
+
bnb_4bit_compute_dtype=torch.float16,
|
| 93 |
+
bnb_4bit_use_double_quant=True,
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
def _load_model(self):
|
| 97 |
+
"""Load the model with optimizations."""
|
| 98 |
+
if self.model is not None:
|
| 99 |
+
return
|
| 100 |
+
|
| 101 |
+
print(f"🚀 Loading {self.model_type} model...")
|
| 102 |
+
|
| 103 |
+
# Load tokenizer
|
| 104 |
+
self.tokenizer = AutoTokenizer.from_pretrained(self.model_id, trust_remote_code=True)
|
| 105 |
+
if self.tokenizer.pad_token is None:
|
| 106 |
+
self.tokenizer.pad_token = self.tokenizer.eos_token
|
| 107 |
+
|
| 108 |
+
# Configure precision
|
| 109 |
+
quantization_config = None
|
| 110 |
+
dtype = None
|
| 111 |
+
banner = ""
|
| 112 |
+
|
| 113 |
+
if self.precision == "fp16":
|
| 114 |
+
dtype = torch.float16
|
| 115 |
+
banner = "FP16 precision"
|
| 116 |
+
elif self.precision == "int8":
|
| 117 |
+
quantization_config = BitsAndBytesConfig(load_in_8bit=True)
|
| 118 |
+
banner = "INT8 quantization"
|
| 119 |
+
elif self.precision == "int4":
|
| 120 |
+
quantization_config = self._create_quantization_config()
|
| 121 |
+
banner = "INT4 (nf4) quantization"
|
| 122 |
+
else:
|
| 123 |
+
dtype = torch.float16
|
| 124 |
+
banner = f"Unknown precision '{self.precision}', defaulting to FP16"
|
| 125 |
+
|
| 126 |
+
# Load base model based on type
|
| 127 |
+
if self.model_type == "codet5":
|
| 128 |
+
self.model = AutoModelForSeq2SeqLM.from_pretrained(
|
| 129 |
+
self.model_id,
|
| 130 |
+
device_map="auto",
|
| 131 |
+
torch_dtype=dtype,
|
| 132 |
+
quantization_config=quantization_config,
|
| 133 |
+
trust_remote_code=True,
|
| 134 |
+
)
|
| 135 |
+
print(f"✅ CodeT5+ loaded with {banner}!")
|
| 136 |
+
|
| 137 |
+
elif self.model_type == "deepseek-finetuned":
|
| 138 |
+
# Load base DeepSeek model
|
| 139 |
+
base_model = AutoModelForCausalLM.from_pretrained(
|
| 140 |
+
self.model_id,
|
| 141 |
+
device_map="auto",
|
| 142 |
+
torch_dtype=dtype,
|
| 143 |
+
quantization_config=quantization_config,
|
| 144 |
+
trust_remote_code=True,
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
# Load LoRA adapters if path exists
|
| 148 |
+
if self.adapter_path and os.path.exists(self.adapter_path):
|
| 149 |
+
print(f"🔗 Loading LoRA adapters from {self.adapter_path}...")
|
| 150 |
+
self.model = PeftModel.from_pretrained(base_model, self.adapter_path)
|
| 151 |
+
print(f"✅ Fine-tuned DeepSeek loaded with {banner}!")
|
| 152 |
+
else:
|
| 153 |
+
print(f"⚠️ Adapter path not found: {self.adapter_path}")
|
| 154 |
+
print(f"✅ Using base DeepSeek model with {banner}")
|
| 155 |
+
self.model = base_model
|
| 156 |
+
|
| 157 |
+
def _create_prompt(self, code: str) -> str:
|
| 158 |
+
"""Create prompt based on model type."""
|
| 159 |
+
if self.model_type == "codet5":
|
| 160 |
+
return f"""Analyze this code for bugs, performance issues, and security concerns:
|
| 161 |
+
|
| 162 |
+
{code}
|
| 163 |
+
|
| 164 |
+
Analysis:"""
|
| 165 |
+
|
| 166 |
+
elif self.model_type == "deepseek-finetuned":
|
| 167 |
+
return f"""<s>[INST] Analyze this code for bugs, performance, and security issues. Give a quality score from 1-100 and provide a detailed analysis.
|
| 168 |
+
|
| 169 |
+
Code:
|
| 170 |
+
```
|
| 171 |
+
{code}
|
| 172 |
+
``` [/INST]"""
|
| 173 |
+
|
| 174 |
+
return code
|
| 175 |
+
|
| 176 |
+
def _extract_response(self, full_text: str, prompt: str) -> str:
|
| 177 |
+
"""Extract the actual response from generated text."""
|
| 178 |
+
if self.model_type == "codet5":
|
| 179 |
+
# Remove prompt from response
|
| 180 |
+
return full_text[len(prompt):].strip()
|
| 181 |
+
|
| 182 |
+
elif self.model_type == "deepseek-finetuned":
|
| 183 |
+
# Extract response after [/INST]
|
| 184 |
+
if '[/INST]' in full_text:
|
| 185 |
+
return full_text.split('[/INST]')[-1].strip()
|
| 186 |
+
return full_text.strip()
|
| 187 |
+
|
| 188 |
+
return full_text.strip()
|
| 189 |
+
|
| 190 |
+
def _get_cache_key(self, code: str) -> str:
|
| 191 |
+
"""Generate cache key for code."""
|
| 192 |
+
# Include model type in cache key
|
| 193 |
+
combined = f"{self.model_type}:{code}"
|
| 194 |
+
return hashlib.md5(combined.encode()).hexdigest()
|
| 195 |
+
|
| 196 |
+
def _load_cache(self):
|
| 197 |
+
"""Load cached results from disk."""
|
| 198 |
+
cache_file = os.path.join(self.cache_dir, "analysis_cache_enhanced.json")
|
| 199 |
+
if os.path.exists(cache_file):
|
| 200 |
+
try:
|
| 201 |
+
with open(cache_file, 'r') as f:
|
| 202 |
+
self.cache = json.load(f)
|
| 203 |
+
print(f"📁 Loaded {len(self.cache)} cached analyses")
|
| 204 |
+
except:
|
| 205 |
+
self.cache = {}
|
| 206 |
+
|
| 207 |
+
def _save_cache(self):
|
| 208 |
+
"""Save cache to disk."""
|
| 209 |
+
cache_file = os.path.join(self.cache_dir, "analysis_cache_enhanced.json")
|
| 210 |
+
with open(cache_file, 'w') as f:
|
| 211 |
+
json.dump(self.cache, f)
|
| 212 |
+
|
| 213 |
+
def _check_cache(self, code: str) -> Optional[Dict[str, Any]]:
|
| 214 |
+
"""Check if analysis is cached."""
|
| 215 |
+
cache_key = self._get_cache_key(code)
|
| 216 |
+
return self.cache.get(cache_key)
|
| 217 |
+
|
| 218 |
+
def _save_to_cache(self, code: str, result: Dict[str, Any]):
|
| 219 |
+
"""Save analysis result to cache."""
|
| 220 |
+
cache_key = self._get_cache_key(code)
|
| 221 |
+
self.cache[cache_key] = result
|
| 222 |
+
self._save_cache()
|
| 223 |
+
|
| 224 |
+
def analyze_code_streaming(
|
| 225 |
+
self,
|
| 226 |
+
code: str,
|
| 227 |
+
show_progress: bool = True,
|
| 228 |
+
mode: str = "detailed",
|
| 229 |
+
) -> Generator[str, None, Dict[str, Any]]:
|
| 230 |
+
"""
|
| 231 |
+
Analyze code with streaming response and progress indicators.
|
| 232 |
+
|
| 233 |
+
Args:
|
| 234 |
+
code: Code to analyze
|
| 235 |
+
show_progress: Whether to show progress indicators
|
| 236 |
+
mode: Analysis mode ("quick" or "detailed")
|
| 237 |
+
|
| 238 |
+
Yields:
|
| 239 |
+
str: Partial analysis results
|
| 240 |
+
"""
|
| 241 |
+
# Check cache first
|
| 242 |
+
cached_result = self._check_cache(code)
|
| 243 |
+
if cached_result:
|
| 244 |
+
print("⚡ Using cached result!")
|
| 245 |
+
yield cached_result["analysis"]
|
| 246 |
+
return cached_result
|
| 247 |
+
|
| 248 |
+
# Load model if not loaded
|
| 249 |
+
self._load_model()
|
| 250 |
+
|
| 251 |
+
# Create prompt
|
| 252 |
+
prompt = self._create_prompt(code)
|
| 253 |
+
|
| 254 |
+
# Tokenize input
|
| 255 |
+
inputs = self.tokenizer(
|
| 256 |
+
prompt,
|
| 257 |
+
return_tensors="pt",
|
| 258 |
+
truncation=True,
|
| 259 |
+
max_length=1024 if self.model_type == "deepseek-finetuned" else 512,
|
| 260 |
+
padding=True,
|
| 261 |
+
)
|
| 262 |
+
device = next(self.model.parameters()).device
|
| 263 |
+
inputs = {k: v.to(device) for k, v in inputs.items()}
|
| 264 |
+
|
| 265 |
+
# Generate analysis
|
| 266 |
+
start_time = time.time()
|
| 267 |
+
|
| 268 |
+
if show_progress:
|
| 269 |
+
print(f"🔍 Analyzing code with {self.model_type}...")
|
| 270 |
+
progress_bar = tqdm(total=100, desc="Analysis Progress")
|
| 271 |
+
|
| 272 |
+
try:
|
| 273 |
+
with torch.no_grad():
|
| 274 |
+
max_new = self.detailed_max_new_tokens if mode == "detailed" else self.quick_max_new_tokens
|
| 275 |
+
|
| 276 |
+
# Generation parameters based on model type
|
| 277 |
+
if self.model_type == "codet5":
|
| 278 |
+
num_beams = 2 if mode == "detailed" else 1
|
| 279 |
+
outputs = self.model.generate(
|
| 280 |
+
inputs["input_ids"],
|
| 281 |
+
attention_mask=inputs.get("attention_mask"),
|
| 282 |
+
max_new_tokens=max_new,
|
| 283 |
+
num_beams=num_beams,
|
| 284 |
+
do_sample=False,
|
| 285 |
+
pad_token_id=self.tokenizer.eos_token_id,
|
| 286 |
+
use_cache=True,
|
| 287 |
+
)
|
| 288 |
+
else: # deepseek-finetuned
|
| 289 |
+
outputs = self.model.generate(
|
| 290 |
+
**inputs,
|
| 291 |
+
max_new_tokens=max_new,
|
| 292 |
+
temperature=0.7,
|
| 293 |
+
do_sample=True,
|
| 294 |
+
pad_token_id=self.tokenizer.eos_token_id,
|
| 295 |
+
eos_token_id=self.tokenizer.eos_token_id,
|
| 296 |
+
)
|
| 297 |
+
|
| 298 |
+
if show_progress:
|
| 299 |
+
progress_bar.update(50)
|
| 300 |
+
|
| 301 |
+
# Decode analysis
|
| 302 |
+
full_text = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 303 |
+
analysis_text = self._extract_response(full_text, prompt)
|
| 304 |
+
|
| 305 |
+
if show_progress:
|
| 306 |
+
progress_bar.update(50)
|
| 307 |
+
progress_bar.close()
|
| 308 |
+
|
| 309 |
+
# Calculate quality score
|
| 310 |
+
quality_score = self._calculate_quality_score(analysis_text)
|
| 311 |
+
|
| 312 |
+
total_time = time.time() - start_time
|
| 313 |
+
|
| 314 |
+
# Create result
|
| 315 |
+
result = {
|
| 316 |
+
"analysis": analysis_text,
|
| 317 |
+
"quality_score": quality_score,
|
| 318 |
+
"execution_time": total_time,
|
| 319 |
+
"model": self.model_id,
|
| 320 |
+
"model_type": self.model_type,
|
| 321 |
+
"cached": False
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
# Save to cache
|
| 325 |
+
self._save_to_cache(code, result)
|
| 326 |
+
|
| 327 |
+
# Yield the analysis
|
| 328 |
+
yield analysis_text
|
| 329 |
+
|
| 330 |
+
return result
|
| 331 |
+
|
| 332 |
+
except Exception as e:
|
| 333 |
+
if show_progress:
|
| 334 |
+
progress_bar.close()
|
| 335 |
+
raise e
|
| 336 |
+
|
| 337 |
+
def analyze_code_fast(self, code: str, mode: str = "quick") -> Dict[str, Any]:
|
| 338 |
+
"""
|
| 339 |
+
Fast analysis without streaming (for batch processing).
|
| 340 |
+
|
| 341 |
+
Args:
|
| 342 |
+
code: Code to analyze
|
| 343 |
+
mode: Analysis mode ("quick" or "detailed")
|
| 344 |
+
|
| 345 |
+
Returns:
|
| 346 |
+
Dict: Analysis result
|
| 347 |
+
"""
|
| 348 |
+
# Check cache first
|
| 349 |
+
cached_result = self._check_cache(code)
|
| 350 |
+
if cached_result:
|
| 351 |
+
cached_result["cached"] = True
|
| 352 |
+
return cached_result
|
| 353 |
+
|
| 354 |
+
# Load model if not loaded
|
| 355 |
+
self._load_model()
|
| 356 |
+
|
| 357 |
+
# Create prompt
|
| 358 |
+
prompt = self._create_prompt(code)
|
| 359 |
+
|
| 360 |
+
# Tokenize input
|
| 361 |
+
inputs = self.tokenizer(
|
| 362 |
+
prompt,
|
| 363 |
+
return_tensors="pt",
|
| 364 |
+
truncation=True,
|
| 365 |
+
max_length=1024 if self.model_type == "deepseek-finetuned" else 512,
|
| 366 |
+
padding=True,
|
| 367 |
+
)
|
| 368 |
+
device = next(self.model.parameters()).device
|
| 369 |
+
inputs = {k: v.to(device) for k, v in inputs.items()}
|
| 370 |
+
|
| 371 |
+
# Generate analysis
|
| 372 |
+
start_time = time.time()
|
| 373 |
+
|
| 374 |
+
with torch.no_grad():
|
| 375 |
+
max_new = self.quick_max_new_tokens if mode == "quick" else self.detailed_max_new_tokens
|
| 376 |
+
|
| 377 |
+
if self.model_type == "codet5":
|
| 378 |
+
num_beams = 1 if mode == "quick" else 2
|
| 379 |
+
outputs = self.model.generate(
|
| 380 |
+
inputs["input_ids"],
|
| 381 |
+
attention_mask=inputs.get("attention_mask"),
|
| 382 |
+
max_new_tokens=max_new,
|
| 383 |
+
num_beams=num_beams,
|
| 384 |
+
do_sample=False,
|
| 385 |
+
pad_token_id=self.tokenizer.eos_token_id,
|
| 386 |
+
use_cache=True,
|
| 387 |
+
)
|
| 388 |
+
else: # deepseek-finetuned
|
| 389 |
+
outputs = self.model.generate(
|
| 390 |
+
**inputs,
|
| 391 |
+
max_new_tokens=max_new,
|
| 392 |
+
temperature=0.7,
|
| 393 |
+
do_sample=True,
|
| 394 |
+
pad_token_id=self.tokenizer.eos_token_id,
|
| 395 |
+
eos_token_id=self.tokenizer.eos_token_id,
|
| 396 |
+
)
|
| 397 |
+
|
| 398 |
+
# Decode analysis
|
| 399 |
+
full_text = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 400 |
+
analysis_text = self._extract_response(full_text, prompt)
|
| 401 |
+
|
| 402 |
+
# Calculate quality score
|
| 403 |
+
quality_score = self._calculate_quality_score(analysis_text)
|
| 404 |
+
|
| 405 |
+
total_time = time.time() - start_time
|
| 406 |
+
|
| 407 |
+
# Create result
|
| 408 |
+
result = {
|
| 409 |
+
"analysis": analysis_text,
|
| 410 |
+
"quality_score": quality_score,
|
| 411 |
+
"execution_time": total_time,
|
| 412 |
+
"model": self.model_id,
|
| 413 |
+
"model_type": self.model_type,
|
| 414 |
+
"cached": False
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
# Save to cache
|
| 418 |
+
self._save_to_cache(code, result)
|
| 419 |
+
|
| 420 |
+
return result
|
| 421 |
+
|
| 422 |
+
def _calculate_quality_score(self, analysis_text: str) -> int:
|
| 423 |
+
"""
|
| 424 |
+
Calculate quality score for analysis.
|
| 425 |
+
|
| 426 |
+
Args:
|
| 427 |
+
analysis_text: Analysis text
|
| 428 |
+
|
| 429 |
+
Returns:
|
| 430 |
+
int: Quality score (0-100)
|
| 431 |
+
"""
|
| 432 |
+
# Try to extract score from DeepSeek output first
|
| 433 |
+
if "Quality Score:" in analysis_text or "quality score" in analysis_text.lower():
|
| 434 |
+
import re
|
| 435 |
+
score_match = re.search(r'(?:Quality Score:|quality score:?)\s*(\d+)', analysis_text, re.IGNORECASE)
|
| 436 |
+
if score_match:
|
| 437 |
+
return int(score_match.group(1))
|
| 438 |
+
|
| 439 |
+
# Fallback to heuristic calculation
|
| 440 |
+
score = 0
|
| 441 |
+
analysis_lower = analysis_text.lower()
|
| 442 |
+
|
| 443 |
+
if any(word in analysis_lower for word in ['bug', 'error', 'issue', 'problem', 'flaw']):
|
| 444 |
+
score += 20
|
| 445 |
+
|
| 446 |
+
if any(word in analysis_lower for word in ['performance', 'slow', 'efficient', 'complexity', 'optimization']):
|
| 447 |
+
score += 20
|
| 448 |
+
|
| 449 |
+
if any(word in analysis_lower for word in ['security', 'vulnerability', 'safe', 'unsafe', 'risk']):
|
| 450 |
+
score += 20
|
| 451 |
+
|
| 452 |
+
if any(word in analysis_lower for word in ['suggest', 'improve', 'better', 'recommend', 'fix', 'solution']):
|
| 453 |
+
score += 20
|
| 454 |
+
|
| 455 |
+
if len(analysis_text) > 200:
|
| 456 |
+
score += 10
|
| 457 |
+
if len(analysis_text) > 500:
|
| 458 |
+
score += 10
|
| 459 |
+
|
| 460 |
+
return min(score, 100)
|
| 461 |
+
|
| 462 |
+
def get_model_info(self) -> Dict[str, Any]:
|
| 463 |
+
"""Get information about the loaded model."""
|
| 464 |
+
if self.model is None:
|
| 465 |
+
return {"status": "Model not loaded"}
|
| 466 |
+
|
| 467 |
+
param_count = sum(p.numel() for p in self.model.parameters())
|
| 468 |
+
trainable_params = sum(p.numel() for p in self.model.parameters() if p.requires_grad)
|
| 469 |
+
device = next(self.model.parameters()).device
|
| 470 |
+
|
| 471 |
+
info = {
|
| 472 |
+
"model_id": self.model_id,
|
| 473 |
+
"model_type": self.model_type,
|
| 474 |
+
"parameters": param_count,
|
| 475 |
+
"trainable_parameters": trainable_params,
|
| 476 |
+
"device": str(device),
|
| 477 |
+
"precision": self.precision,
|
| 478 |
+
"quick_max_new_tokens": self.quick_max_new_tokens,
|
| 479 |
+
"detailed_max_new_tokens": self.detailed_max_new_tokens,
|
| 480 |
+
"cache_size": len(self.cache)
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
if self.adapter_path:
|
| 484 |
+
info["adapter_path"] = self.adapter_path
|
| 485 |
+
info["using_adapters"] = os.path.exists(self.adapter_path) if self.adapter_path else False
|
| 486 |
+
|
| 487 |
+
return info
|
| 488 |
+
|
| 489 |
+
|
| 490 |
+
def main():
|
| 491 |
+
"""Demo of the enhanced analyzer."""
|
| 492 |
+
print("🚀 Enhanced Code Analyzer Demo")
|
| 493 |
+
print("=" * 60)
|
| 494 |
+
|
| 495 |
+
# Test code
|
| 496 |
+
test_code = """
|
| 497 |
+
def calculate_fibonacci(n):
|
| 498 |
+
if n <= 0:
|
| 499 |
+
return 0
|
| 500 |
+
elif n == 1:
|
| 501 |
+
return 1
|
| 502 |
+
else:
|
| 503 |
+
return calculate_fibonacci(n-1) + calculate_fibonacci(n-2)
|
| 504 |
+
|
| 505 |
+
result = calculate_fibonacci(35)
|
| 506 |
+
print(result)
|
| 507 |
+
"""
|
| 508 |
+
|
| 509 |
+
print(f"Test Code:\n{test_code}")
|
| 510 |
+
print("=" * 60)
|
| 511 |
+
|
| 512 |
+
# Test with CodeT5+
|
| 513 |
+
print("\n🔵 Testing with CodeT5+ (Base Model):")
|
| 514 |
+
print("-" * 60)
|
| 515 |
+
analyzer_codet5 = EnhancedCodeAnalyzer(model_type="codet5")
|
| 516 |
+
result_codet5 = analyzer_codet5.analyze_code_fast(test_code)
|
| 517 |
+
print(f"Analysis: {result_codet5['analysis'][:300]}...")
|
| 518 |
+
print(f"Quality Score: {result_codet5['quality_score']}/100")
|
| 519 |
+
print(f"Execution Time: {result_codet5['execution_time']:.2f}s")
|
| 520 |
+
|
| 521 |
+
# Test with Fine-tuned DeepSeek
|
| 522 |
+
print("\n🟢 Testing with Fine-tuned DeepSeek:")
|
| 523 |
+
print("-" * 60)
|
| 524 |
+
analyzer_deepseek = EnhancedCodeAnalyzer(
|
| 525 |
+
model_type="deepseek-finetuned",
|
| 526 |
+
adapter_path="./fine-tuned-analyst"
|
| 527 |
+
)
|
| 528 |
+
result_deepseek = analyzer_deepseek.analyze_code_fast(test_code)
|
| 529 |
+
print(f"Analysis: {result_deepseek['analysis'][:300]}...")
|
| 530 |
+
print(f"Quality Score: {result_deepseek['quality_score']}/100")
|
| 531 |
+
print(f"Execution Time: {result_deepseek['execution_time']:.2f}s")
|
| 532 |
+
|
| 533 |
+
# Show model comparison
|
| 534 |
+
print("\n📊 Model Comparison:")
|
| 535 |
+
print("-" * 60)
|
| 536 |
+
print(f"CodeT5+ Info: {analyzer_codet5.get_model_info()}")
|
| 537 |
+
print(f"DeepSeek Info: {analyzer_deepseek.get_model_info()}")
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
if __name__ == "__main__":
|
| 541 |
+
main()
|
| 542 |
+
|
requirements.txt
CHANGED
|
@@ -3,4 +3,13 @@ openai>=1.0.0
|
|
| 3 |
anthropic>=0.25.0
|
| 4 |
python-dotenv>=1.0.0
|
| 5 |
requests>=2.32.0
|
| 6 |
-
typing-extensions>=4.0.0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
anthropic>=0.25.0
|
| 4 |
python-dotenv>=1.0.0
|
| 5 |
requests>=2.32.0
|
| 6 |
+
typing-extensions>=4.0.0
|
| 7 |
+
|
| 8 |
+
# Fine-tuning libraries
|
| 9 |
+
torch>=2.0.0
|
| 10 |
+
transformers>=4.35.0
|
| 11 |
+
datasets>=2.14.0
|
| 12 |
+
peft>=0.6.0
|
| 13 |
+
trl>=0.7.0
|
| 14 |
+
bitsandbytes>=0.41.0
|
| 15 |
+
accelerate>=0.24.0
|
streamlit.bat
DELETED
|
@@ -1,2 +0,0 @@
|
|
| 1 |
-
@echo off
|
| 2 |
-
python -m streamlit %*
|
|
|
|
|
|
|
|
|
test_app.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
| 1 |
-
import streamlit as st
|
| 2 |
-
from analyzer import CodeAnalyzer
|
| 3 |
-
|
| 4 |
-
# Simple test app
|
| 5 |
-
st.title("🔍 LLM Code Analyzer - Test")
|
| 6 |
-
|
| 7 |
-
try:
|
| 8 |
-
analyzer = CodeAnalyzer()
|
| 9 |
-
available_models = analyzer.available_models
|
| 10 |
-
|
| 11 |
-
st.success(f"✅ Analyzer loaded successfully!")
|
| 12 |
-
st.info(f"📊 Available models: {len(available_models)}")
|
| 13 |
-
|
| 14 |
-
for model_key, model_name in available_models.items():
|
| 15 |
-
st.write(f"• {model_name}")
|
| 16 |
-
|
| 17 |
-
# Simple code input
|
| 18 |
-
code_input = st.text_area("Enter code to analyze:",
|
| 19 |
-
value="def hello():\n print('Hello, World!')",
|
| 20 |
-
height=150)
|
| 21 |
-
|
| 22 |
-
if st.button("Analyze"):
|
| 23 |
-
if code_input.strip():
|
| 24 |
-
with st.spinner("Analyzing..."):
|
| 25 |
-
result = analyzer.analyze_code(code_input, list(available_models.keys())[0])
|
| 26 |
-
st.json(result)
|
| 27 |
-
else:
|
| 28 |
-
st.warning("Please enter some code")
|
| 29 |
-
|
| 30 |
-
except Exception as e:
|
| 31 |
-
st.error(f"Error: {str(e)}")
|
| 32 |
-
st.write("Debug info:")
|
| 33 |
-
st.write(f"Python version: {sys.version}")
|
| 34 |
-
st.write(f"Working directory: {os.getcwd()}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|