File size: 4,306 Bytes
7c012de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
07b8ac9
7c012de
 
 
 
 
 
 
 
 
4e2a9bc
 
7c012de
 
 
 
 
 
 
4e2a9bc
 
7c012de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4e2a9bc
7c012de
 
 
 
4e2a9bc
7c012de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**
 * Modal API Client for Serverless Compute Integration
 */

interface ModalConfig {
  tokenId: string;
  tokenSecret: string;
  baseUrl: string;
}

interface DocumentProcessingTask {
  taskId: string;
  status: 'pending' | 'running' | 'completed' | 'failed';
  result?: any;
  error?: string;
}

interface VectorProcessingRequest {
  documents: Array<{
    id: string;
    content: string;
    metadata?: Record<string, any>;
  }>;
  modelName?: string;
  batchSize?: number;
}

class ModalClient {
  private config: ModalConfig;
  private authToken: string;

  constructor() {
    // Use environment variables - NEVER hardcode credentials
    const tokenId = process.env.MODAL_TOKEN_ID;
    const tokenSecret = process.env.MODAL_TOKEN_SECRET;
    
    if (!tokenId || !tokenSecret) {
      throw new Error('Modal credentials not configured. Please set MODAL_TOKEN_ID and MODAL_TOKEN_SECRET environment variables.');
    }
    
    this.config = {
      tokenId,
      tokenSecret,
      baseUrl: 'https://fazeelusmani18--knowledgebridge-main-fastapi-app.modal.run'
    };
    
    // Create base64 encoded auth token
    this.authToken = Buffer.from(`${this.config.tokenId}:${this.config.tokenSecret}`).toString('base64');
  }

  private async makeRequest(endpoint: string, options: RequestInit = {}) {
    const url = `${this.config.baseUrl}${endpoint}`;
    
    console.log(`Modal API request: ${options.method || 'GET'} ${url}`);
    
    const response = await fetch(url, {
      ...options,
      headers: {
        'Content-Type': 'application/json',
        ...options.headers,
      },
    });
    
    console.log(`Modal API response: ${response.status} ${response.statusText}`);

    if (!response.ok) {
      throw new Error(`Modal API request failed: ${response.status} ${response.statusText}`);
    }

    return response.json();
  }

  /**
   * Process documents in batch using Modal's serverless compute
   */
  async batchProcessDocuments(request: VectorProcessingRequest): Promise<DocumentProcessingTask> {
    return this.makeRequest('/batch-process', {
      method: 'POST',
      body: JSON.stringify({
        documents: request.documents,
        config: {
          modelName: request.modelName || 'text-embedding-3-small',
          batchSize: request.batchSize || 50,
          computeResources: {
            cpu: 2,
            memory: '4Gi'
          }
        }
      })
    });
  }

  /**
   * Get status of a processing task
   */
  async getTaskStatus(taskId: string): Promise<DocumentProcessingTask> {
    return this.makeRequest(`/task/${taskId}`);
  }

  /**
   * Build FAISS index using Modal's distributed computing
   */
  async buildVectorIndex(documents: any[], indexConfig?: any): Promise<DocumentProcessingTask> {
    const indexName = indexConfig?.indexName || 'main_index';
    return this.makeRequest('/build-index', {
      method: 'POST',
      body: JSON.stringify({
        documents,
        index_name: indexName
      })
    });
  }

  /**
   * Perform high-performance vector search
   */
  async vectorSearch(query: string, indexId: string, k: number = 10): Promise<any> {
    return this.makeRequest('/vector-search', {
      method: 'POST',
      body: JSON.stringify({
        query,
        indexId,
        k,
        includeMetadata: true
      })
    });
  }

  /**
   * Extract text from documents using OCR
   */
  async extractTextFromDocuments(documentUrls: string[]): Promise<DocumentProcessingTask> {
    return this.makeRequest('/ocr-extract', {
      method: 'POST',
      body: JSON.stringify({
        documentUrls,
        config: {
          languages: ['en'],
          outputFormat: 'structured'
        }
      })
    });
  }

  /**
   * Auto-categorize documents using distributed ML
   */
  async categorizeDocuments(documents: any[]): Promise<DocumentProcessingTask> {
    return this.makeRequest('/categorize', {
      method: 'POST',
      body: JSON.stringify({
        documents,
        categories: [
          'academic_paper',
          'technical_documentation',
          'research_report',
          'code_repository',
          'blog_post',
          'news_article'
        ]
      })
    });
  }
}

export const modalClient = new ModalClient();
export type { DocumentProcessingTask, VectorProcessingRequest };