remcode
Version:
Turn your AI assistant into a codebase expert. Intelligent code analysis, semantic search, and software engineering guidance through MCP integration.
184 lines (183 loc) • 7.96 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SemanticSearch = void 0;
const logger_1 = require("../utils/logger");
const pinecone_1 = require("../vectorizers/storage/pinecone");
const manager_1 = require("../vectorizers/embedders/manager");
const dotenv = __importStar(require("dotenv"));
// Load environment variables
dotenv.config();
const logger = (0, logger_1.getLogger)('SemanticSearch');
/**
* Handles semantic code search using vector embeddings
*/
class SemanticSearch {
constructor(options = {}) {
this.storage = null;
this.embeddingManager = null;
this.initialized = false;
this.options = {
pineconeApiKey: options.pineconeApiKey || process.env.PINECONE_API_KEY,
pineconeIndexName: options.pineconeIndexName || 'remcode-default',
pineconeEnvironment: options.pineconeEnvironment || 'gcp-starter',
pineconeNamespace: options.pineconeNamespace || 'default',
huggingfaceToken: options.huggingfaceToken || process.env.HUGGINGFACE_TOKEN,
embeddingModel: options.embeddingModel || 'BAAI/bge-base-en-v1.5',
fallbackModel: options.fallbackModel || 'BAAI/bge-small-en-v1.5',
embeddingDimension: options.embeddingDimension || 768,
batchSize: options.batchSize || 10
};
}
async initialize() {
logger.info('Initializing semantic search...');
if (!this.options.pineconeApiKey) {
throw new Error('Pinecone API key is required for semantic search');
}
if (!this.options.huggingfaceToken) {
throw new Error('HuggingFace token is required for semantic search');
}
try {
// Initialize Pinecone storage
this.storage = new pinecone_1.PineconeStorage({
apiKey: this.options.pineconeApiKey,
indexName: this.options.pineconeIndexName,
namespace: this.options.pineconeNamespace,
dimension: this.options.embeddingDimension || 768
});
await this.storage.initialize();
// Initialize embedding manager
this.embeddingManager = new manager_1.EmbeddingManager({
primary: this.options.embeddingModel,
fallback: this.options.fallbackModel,
batchSize: this.options.batchSize,
token: this.options.huggingfaceToken,
dimension: this.options.embeddingDimension || 768
});
this.initialized = true;
logger.info('Semantic search initialized successfully');
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Failed to initialize semantic search: ${errorMessage}`);
throw new Error(`Initialization failed: ${errorMessage}`);
}
}
async search(query, topK = 10, filters) {
if (!this.initialized || !this.storage || !this.embeddingManager) {
throw new Error('Semantic search not initialized. Call initialize() first.');
}
if (!query.trim()) {
throw new Error('Search query cannot be empty');
}
logger.info(`Searching for: "${query}" (top ${topK} results)`);
try {
// 1. Generate embedding for the query
const queryChunk = {
content: query,
metadata: {
file_path: 'query',
strategy: 'query',
chunk_type: 'query'
}
};
const embeddedQueries = await this.embeddingManager.embedChunks([queryChunk]);
if (!embeddedQueries[0].embedding) {
throw new Error('Failed to generate embedding for query');
}
// 2. Search Pinecone for similar vectors
const matches = await this.storage.queryVectors(embeddedQueries[0].embedding, topK, filters, this.options.pineconeNamespace);
// 3. Format results for consistent API
const formattedResults = matches.map(match => ({
id: match.id || '',
score: match.score || 0,
content: match.metadata?.content || '',
metadata: {
filePath: match.metadata?.file_path || '',
language: match.metadata?.language || '',
chunkType: match.metadata?.chunk_type || '',
startLine: match.metadata?.start_line,
endLine: match.metadata?.end_line,
functionName: match.metadata?.function_name,
className: match.metadata?.class_name,
...match.metadata
}
}));
logger.info(`Found ${formattedResults.length} results for query: "${query}"`);
return formattedResults;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Search failed: ${errorMessage}`);
throw new Error(`Search failed: ${errorMessage}`);
}
}
async searchSimilarCode(codeSnippet, topK = 5) {
return this.search(`code: ${codeSnippet}`, topK, { chunk_type: 'function' });
}
async searchPatterns(pattern, topK = 10) {
return this.search(`pattern: ${pattern}`, topK);
}
async searchFunctionality(description, topK = 10) {
return this.search(`functionality: ${description}`, topK);
}
formatSearchResults(matches) {
return matches.map(match => ({
id: match.id,
score: match.score,
content: match.metadata?.content || '',
metadata: {
filePath: match.metadata?.file_path || '',
language: match.metadata?.language || '',
chunkType: match.metadata?.chunk_type || '',
startLine: match.metadata?.start_line,
endLine: match.metadata?.end_line,
functionName: match.metadata?.function_name,
className: match.metadata?.class_name,
...match.metadata
}
}));
}
async getStats() {
if (!this.initialized || !this.storage) {
throw new Error('Semantic search not initialized');
}
return await this.storage.getIndexStats();
}
isInitialized() {
return this.initialized;
}
}
exports.SemanticSearch = SemanticSearch;
;