Skip to content

Commit 2d9b8ac

Browse files
committed
fix Error generating embeddings: BadRequestError: 400 Requested 405717 tokens, max 300000 tokens per request
1 parent e7b981c commit 2d9b8ac

File tree

4 files changed

+88
-72
lines changed

4 files changed

+88
-72
lines changed

action.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ inputs:
5454
description: 'OpenAI embedding model to use'
5555
required: false
5656
default: 'text-embedding-3-small'
57+
58+
max_tokens_per_batch:
59+
description: 'Max tokens per batch'
60+
required: false
61+
default: 250000
5762

5863
file_extensions:
5964
description: 'Comma-separated list of file extensions to include'

index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ async function run() {
1515
// Налаштування для фільтрації файлів
1616
const fileExtensions = (core.getInput('file_extensions') || '.js,.ts,.jsx,.tsx,.html,.css,.md,.txt').split(',');
1717
const excludePatterns = (core.getInput('exclude_patterns') || 'node_modules/**,dist/**,.git/**').split(',');
18-
18+
19+
const MAX_TOKENS_PER_BATCH = core.getInput('max_tokens_per_batch') || 250000;
20+
1921
// Підключаємося до векторної бази даних
2022
let dbAdapter;
2123

@@ -56,7 +58,8 @@ async function run() {
5658

5759
// Встановлюємо OpenAI API ключ 1
5860
process.env.OPENAI_API_KEY = openaiApiKey;
59-
61+
process.env.MAX_TOKENS_PER_BATCH = MAX_TOKENS_PER_BATCH;
62+
6063
// Запускаємо сканування репозиторію
6164
const repoPath = process.env.GITHUB_WORKSPACE || '.';
6265

src/utils/embeddings.js

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/utils/fileUtils.js

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,117 @@
11
const fs = require('fs').promises;
22
const path = require('path');
33
const { 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

49115
module.exports = {
50-
getEmbedding,
51116
processFiles
52117
};

0 commit comments

Comments
 (0)