11const fs = require ( 'fs' ) . promises ;
22const path = require ( 'path' ) ;
33const { RecursiveCharacterTextSplitter } = require ( '@langchain/textsplitters' ) ;
4- const { getEmbedding } = require ( './embeddings' ) ;
54
6- async function processFiles ( { files, dbAdapter, repoPath, openaiModel } ) {
5+ async function processFiles ( { files, dbAdapter, repoPath, openaiModel, collectionName = null } ) {
76 // Створюємо текстовий сплітер
87 const textSplitter = new RecursiveCharacterTextSplitter ( {
98 chunkSize : 1000 ,
10- chunkOverlap : 200
9+ chunkOverlap : 200 ,
10+ lengthFunction : ( text ) => {
11+ // Проста оцінка кількості токенів: ~4 символи = 1 токен
12+ return Math . ceil ( text . length / 4 ) ;
13+ }
1114 } ) ;
1215
16+ // Максимальна кількість токенів у пакеті документів
17+ const MAX_TOKENS_PER_BATCH = process . env . MAX_TOKENS_PER_BATCH || 250000 ; // Беремо з запасом від 300000
18+
19+ let documents = [ ] ;
20+ let metadatas = [ ] ;
21+ let ids = [ ] ;
22+ let currentBatchTokens = 0 ;
23+
24+ const totalFiles = files . length ;
25+ let processedFiles = 0 ;
26+ let lastReportedPercentage = - 5 ; // Починаємо з від'ємного значення, щоб гарантовано вивести 0%
27+ let totalChunks = 0 ;
28+ let processedChunks = 0 ;
29+
30+
31+ function reportProgress ( ) {
32+ const percentage = Math . floor ( ( processedFiles / totalFiles ) * 100 ) ;
33+
34+ if ( percentage >= lastReportedPercentage + 5 ) {
35+ console . log ( `Progress: ${ percentage } % (processed ${ processedFiles } /${ totalFiles } files, ${ processedChunks } chunks)` ) ;
36+ lastReportedPercentage = percentage ;
37+ }
38+ }
39+
40+ async function sendBatch ( ) {
41+ if ( documents . length === 0 ) return ;
42+
43+ try {
44+ // Додаємо до бази даних
45+ await dbAdapter . addDocuments ( documents , metadatas , ids , collectionName ) ;
46+
47+ // Очищаємо пакет
48+ documents = [ ] ;
49+ metadatas = [ ] ;
50+ ids = [ ] ;
51+ currentBatchTokens = 0 ;
52+ } catch ( error ) {
53+ console . error ( `Error adding document package:` , error ) ;
54+ }
55+ }
56+
1357 for ( const filePath of files ) {
14- console . log ( `Processing ${ filePath } ` ) ;
1558 try {
1659 const content = await fs . readFile ( filePath , 'utf-8' ) ;
1760
1861 // Розбиваємо на чанки
1962 const chunks = await textSplitter . splitText ( content ) ;
2063 // Готуємо метадані
2164 const relPath = path . relative ( repoPath , filePath ) ;
22-
23- const documents = [ ] ;
24- const metadatas = [ ] ;
25- const ids = [ ] ;
26-
65+
66+ totalChunks += chunks . length ;
67+
2768 for ( let i = 0 ; i < chunks . length ; i ++ ) {
2869 // Унікальний ID для кожного чанка
2970 const chunkId = `${ relPath } _${ i } ` ;
3071
72+ // Оцінка кількості токенів у чанку
73+ const chunkTokens = Math . ceil ( chunks [ i ] . length / 4 ) ;
74+ // Якщо додавання чанка перевищить ліміт токенів - відправляємо накопичений пакет
75+ if ( currentBatchTokens + chunkTokens > MAX_TOKENS_PER_BATCH ) {
76+ await sendBatch ( ) ;
77+ }
78+
3179 documents . push ( chunks [ i ] ) ;
3280 metadatas . push ( {
3381 file_path : relPath ,
3482 chunk_index : i ,
3583 total_chunks : chunks . length
3684 } ) ;
3785 ids . push ( chunkId ) ;
86+ currentBatchTokens += chunkTokens ;
87+ processedChunks ++ ;
88+ }
89+
90+ if ( documents . length > 0 ) {
91+ await sendBatch ( ) ;
3892 }
39-
4093 // Додаємо до бази даних
41- await dbAdapter . addDocuments ( documents , metadatas , ids ) ;
42-
94+ // await dbAdapter.addDocuments(documents, metadatas, ids);
95+
96+ processedFiles ++ ;
97+ reportProgress ( ) ;
98+
4399 } catch ( error ) {
44100 console . error ( `Error processing ${ filePath } :` , error ) ;
101+
102+ processedFiles ++ ;
103+ reportProgress ( ) ;
104+
45105 }
46106 }
107+
108+ // Відправляємо останній пакет
109+ if ( documents . length > 0 ) {
110+ await sendBatch ( ) ;
111+ }
112+
47113}
48114
49115module . exports = {
50- getEmbedding,
51116 processFiles
52117} ;
0 commit comments