codebridge-ai
Version:
Complete fullstack AI coding platform with AST-based code integration and local LLM support. Now with comprehensive web technology support (HTML/CSS/JS) plus JavaScript, Python, Rust, and C++.
374 lines (317 loc) • 10.5 kB
JavaScript
/**
* 다중 언어 모델 테스트 실행기
*/
const fs = require('fs').promises;
const path = require('path');
const OllamaCodeBridge = require('../integrations/ollama-integration');
class MultiLanguageModelTester {
constructor() {
this.models = [
'deepseek-coder:6.7b',
'starcoder2:3b'
// 'codellama:7b' // 설치되어 있다면 추가
];
this.testScenarios = {
javascript: {
basic: {
code: `
function calculateTotal(items) {
let total = 0;
for (let item of items) {
total += item.price;
}
return total;
}`,
tasks: [
"Add input validation and error handling",
"Make the function async and add proper documentation",
"Add unit price calculation with discount support"
]
},
class: {
code: `
class UserService {
constructor() {
this.users = [];
}
addUser(user) {
this.users.push(user);
}
getUser(id) {
return this.users.find(u => u.id === id);
}
}`,
tasks: [
"Add comprehensive error handling and validation",
"Add caching mechanism using @decorator cache",
"Make methods async and add proper error responses"
]
}
},
python: {
basic: {
code: `
def process_data(data):
result = []
for item in data:
if item > 0:
result.append(item * 2)
return result`,
tasks: [
"Add type hints and docstring",
"Add input validation and error handling",
"Convert to use list comprehension and add logging"
]
},
class: {
code: `
class DataProcessor:
def __init__(self):
self.data = []
def add_data(self, item):
self.data.append(item)
def process(self):
return [x * 2 for x in self.data if x > 0]`,
tasks: [
"Add type hints and comprehensive docstrings",
"Add validation and error handling with custom exceptions",
"Add logging and performance monitoring"
]
}
},
'html-css-js': {
component: {
code: `
<div class="user-card">
<h3>User Name</h3>
<p>User email</p>
<button onclick="editUser()">Edit</button>
</div>
<style>
.user-card {
border: 1px solid #ccc;
padding: 10px;
}
</style>
<script>
function editUser() {
alert('Edit functionality');
}
</script>`,
tasks: [
"Make the component accessible with proper ARIA labels",
"Add responsive design with mobile-first approach",
"Convert to modern JavaScript with proper event handling"
]
}
},
cpp: {
basic: {
code: `
#include <vector>
#include <iostream>
class DataManager {
private:
std::vector<int>* data;
public:
DataManager() {
data = new std::vector<int>();
}
void addData(int value) {
data->push_back(value);
}
void printData() {
for(int i = 0; i < data->size(); i++) {
std::cout << (*data)[i] << " ";
}
}
};`,
tasks: [
"Convert to use RAII pattern with smart pointers",
"Add exception safety and proper error handling",
"Add const correctness and modern C++ features"
]
}
},
rust: {
basic: {
code: `
pub struct DataProcessor {
data: Vec<i32>,
}
impl DataProcessor {
pub fn new() -> DataProcessor {
DataProcessor { data: Vec::new() }
}
pub fn add(&mut self, value: i32) {
self.data.push(value);
}
pub fn process(&self) -> Vec<i32> {
let mut result = Vec::new();
for item in &self.data {
if *item > 0 {
result.push(*item * 2);
}
}
result
}
}`,
tasks: [
"Add proper error handling with Result types",
"Optimize using iterators and functional programming",
"Add lifetime annotations and borrowing optimizations"
]
}
}
};
}
async runAllTests() {
console.log('🚀 다중 언어 모델 테스트 시작\\n');
for (const model of this.models) {
console.log(`\\n${'='.repeat(60)}`);
console.log(`🤖 모델 테스트: ${model}`);
console.log(`${'='.repeat(60)}\\n`);
for (const [language, scenarios] of Object.entries(this.testScenarios)) {
console.log(`\\n📁 언어: ${language.toUpperCase()}`);
console.log(`${'-'.repeat(40)}`);
for (const [scenarioName, scenario] of Object.entries(scenarios)) {
await this.runScenarioTest(model, language, scenarioName, scenario);
}
}
}
console.log('\\n✅ 모든 테스트 완료');
await this.generateComparisonReport();
}
async runScenarioTest(model, language, scenarioName, scenario) {
console.log(`\\n🧪 시나리오: ${scenarioName}`);
const ollamaCodeBridge = new OllamaCodeBridge({
model,
temperature: 0.3
});
const results = [];
let currentCode = scenario.code;
for (let i = 0; i < scenario.tasks.length; i++) {
const task = scenario.tasks[i];
console.log(`\\n 📝 작업 ${i + 1}: ${task}`);
const startTime = Date.now();
try {
const result = await ollamaCodeBridge.improveCode(currentCode, task);
const duration = Date.now() - startTime;
const testResult = {
timestamp: new Date().toISOString(),
model,
language,
scenario: scenarioName,
taskIndex: i + 1,
task,
originalCode: currentCode,
success: result.success,
duration,
rawResponse: result.rawResponse,
improvedSnippet: result.improvedSnippet,
finalCode: result.finalCode,
error: result.error
};
results.push(testResult);
if (result.success) {
console.log(` ✅ 성공 (${duration}ms)`);
currentCode = result.finalCode;
} else {
console.log(` ❌ 실패: ${result.error}`);
}
} catch (error) {
console.log(` 💥 예외: ${error.message}`);
results.push({
timestamp: new Date().toISOString(),
model,
language,
scenario: scenarioName,
taskIndex: i + 1,
task,
originalCode: currentCode,
success: false,
duration: Date.now() - startTime,
error: error.message
});
}
}
// 결과 저장
await this.saveTestResults(model, language, scenarioName, results);
// 성공률 출력
const successCount = results.filter(r => r.success).length;
const successRate = (successCount / results.length * 100).toFixed(1);
console.log(`\\n 📊 성공률: ${successCount}/${results.length} (${successRate}%)`);
}
async saveTestResults(model, language, scenarioName, results) {
const dirPath = path.join(__dirname, model.replace(':', '-'), language);
const filePath = path.join(dirPath, `${scenarioName}-${Date.now()}.json`);
try {
await fs.mkdir(dirPath, { recursive: true });
const reportData = {
metadata: {
model,
language,
scenario: scenarioName,
timestamp: new Date().toISOString(),
totalTests: results.length,
successCount: results.filter(r => r.success).length,
successRate: results.filter(r => r.success).length / results.length,
averageDuration: results.reduce((sum, r) => sum + (r.duration || 0), 0) / results.length
},
results
};
await fs.writeFile(filePath, JSON.stringify(reportData, null, 2));
console.log(` 💾 결과 저장: ${filePath}`);
} catch (error) {
console.error(` ❌ 저장 실패: ${error.message}`);
}
}
async generateComparisonReport() {
console.log('\\n📊 비교 리포트 생성 중...');
const reportPath = path.join(__dirname, 'comparison-reports', `comparison-${Date.now()}.md`);
let report = `# 다중 언어 모델 테스트 비교 리포트\\n\\n`;
report += `생성 시간: ${new Date().toISOString()}\\n\\n`;
// 각 모델별 디렉토리 스캔하여 결과 수집
for (const model of this.models) {
report += `## ${model} 모델 결과\\n\\n`;
const modelDir = path.join(__dirname, model.replace(':', '-'));
try {
const languages = await fs.readdir(modelDir);
for (const language of languages) {
report += `### ${language.toUpperCase()}\\n\\n`;
const languageDir = path.join(modelDir, language);
const files = await fs.readdir(languageDir);
for (const file of files.filter(f => f.endsWith('.json'))) {
const filePath = path.join(languageDir, file);
const data = JSON.parse(await fs.readFile(filePath, 'utf8'));
report += `**시나리오**: ${data.metadata.scenario}\\n`;
report += `- 성공률: ${(data.metadata.successRate * 100).toFixed(1)}%\\n`;
report += `- 평균 응답 시간: ${data.metadata.averageDuration.toFixed(0)}ms\\n`;
report += `- 총 테스트: ${data.metadata.totalTests}\\n\\n`;
}
}
} catch (error) {
report += `❌ 모델 결과 로드 실패: ${error.message}\\n\\n`;
}
}
await fs.writeFile(reportPath, report);
console.log(`📋 비교 리포트 저장: ${reportPath}`);
}
}
// 실행
if (require.main === module) {
const tester = new MultiLanguageModelTester();
const args = process.argv.slice(2);
if (args.includes('--help') || args.includes('-h')) {
console.log(`
사용법:
node test-runner.js 전체 테스트 실행
node test-runner.js --model deepseek 특정 모델만 테스트
node test-runner.js --lang javascript 특정 언어만 테스트
node test-runner.js --help 도움말 표시
`);
} else {
tester.runAllTests().catch(console.error);
}
}
module.exports = MultiLanguageModelTester;