Skip to main content
Glama
rag.ts4.49 kB
/** * Modern RAG Service - Cloudflare Worker Native * Optimized for edge computing with zero-dependency architecture */ import type { AppConfig, RAGQuery, RAGResult, SearchResult, } from "../types/index.js"; import { logger } from "../utils/logger.js"; import { DatabaseService } from "./database.js"; import { EmbeddingService } from "./embedding.js"; import { RerankerService } from "./reranker.js"; import { type RankedSearchResult, SearchEngine } from "./search-engine.js"; export class RAGService { readonly database: DatabaseService; readonly embedding: EmbeddingService; private readonly reranker: RerankerService; private readonly searchEngine: SearchEngine; constructor(config: AppConfig, db: D1Database) { // Initialize all services immediately with D1 database this.database = new DatabaseService(config); this.embedding = new EmbeddingService(db); this.reranker = new RerankerService(db); this.searchEngine = new SearchEngine( this.database, this.embedding, this.reranker ); } /** * Initialize - no-op since database initialization is removed */ async initialize(): Promise<void> { // No initialization needed - database trusted ready } /** * Perform RAG query with intelligent processing and detailed timing */ async query(request: RAGQuery): Promise<RAGResult> { const startTime = Date.now(); const { query, result_count = 4 } = request; // No started log - only completion with timing // Input validation if (!query?.trim()) { return this.createErrorResponse( query, "Query cannot be empty. Please provide a search query to find relevant Apple Developer Documentation.", "Try searching for topics like 'SwiftUI navigation', 'iOS app development', or 'API documentation'.", startTime ); } const trimmedQuery = query.trim(); if (trimmedQuery.length > 10000) { return this.createErrorResponse( query, "Query is too long. Please limit your query to 10000 characters or less.", "Try to make your query more concise and specific.", startTime ); } try { // Initialize services (if not already initialized) await this.initialize(); // Execute search const resultCount = Math.min(Math.max(result_count, 1), 20); const searchResult = await this.searchEngine.search(trimmedQuery, { resultCount, }); // Format results const formattedResults = this.formatResults(searchResult.results); const totalTime = Date.now() - startTime; // Log completion with timing logger.info( `RAG query completed (${(totalTime / 1000).toFixed(1)}s) - results: ${formattedResults.length}, query: ${query.substring(0, 50)}` ); return { success: true, query: trimmedQuery, results: formattedResults, additionalUrls: searchResult.additionalUrls, count: formattedResults.length, processing_time_ms: totalTime, }; } catch (error) { logger.error( `RAG query failed for query "${trimmedQuery.substring(0, 50)}": ${error instanceof Error ? error.message : "Unknown error"}` ); return this.createErrorResponse( trimmedQuery, `Search failed: ${error instanceof Error ? error.message : "Unknown error"}`, "Please try again with a different query or check your connection.", startTime ); } } /** * Format search results for MCP response */ private formatResults( results: readonly RankedSearchResult[] ): SearchResult[] { return results.map((result) => ({ id: result.id, url: result.url, title: result.title, content: result.content, contentLength: result.content.length, chunk_index: result.chunk_index, total_chunks: result.total_chunks, mergedChunkIndices: result.mergedChunkIndices, })); } /** * Create standardized error response */ private createErrorResponse( query: string, _error: string, _suggestion: string, startTime: number ): RAGResult { return { success: false, query, results: [], additionalUrls: [], count: 0, processing_time_ms: Date.now() - startTime, }; } /** * Clean up resources */ async close(): Promise<void> { if (this.database) { await this.database.close(); } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adimowis/appler'

If you have feedback or need assistance with the MCP directory API, please join our Discord server