fix: adaptive LLM progress estimation and emit 85% on stream end #6

Merged
admin merged 1 commits from fix/adaptive-llm-progress into main 2026-03-14 13:43:27 +00:00

View File

@@ -145,7 +145,10 @@ export async function convertPdfToStatement(
export type ProgressStage = 'pdf' | 'llm' | 'import'; export type ProgressStage = 'pdf' | 'llm' | 'import';
export type OnProgress = (stage: ProgressStage, progress: number, message: string) => void; export type OnProgress = (stage: ProgressStage, progress: number, message: string) => void;
const EXPECTED_CHARS = 15_000; const LLM_PROGRESS_MIN = 10;
const LLM_PROGRESS_MAX = 85;
const LLM_PROGRESS_RANGE = LLM_PROGRESS_MAX - LLM_PROGRESS_MIN;
const THROTTLE_MS = 300;
export async function convertPdfToStatementStreaming( export async function convertPdfToStatementStreaming(
buffer: Buffer, buffer: Buffer,
@@ -202,22 +205,34 @@ export async function convertPdfToStatementStreaming(
stream: true, stream: true,
}); });
// Estimate expected output size as ~2x the input PDF text length, clamped
const expectedChars = Math.max(2_000, Math.min(text.length * 2, 30_000));
let accumulated = ''; let accumulated = '';
let charsReceived = 0; let charsReceived = 0;
let lastEmitTime = 0;
for await (const chunk of stream) { for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta?.content; const delta = chunk.choices[0]?.delta?.content;
if (delta) { if (delta) {
accumulated += delta; accumulated += delta;
charsReceived += delta.length; charsReceived += delta.length;
const llmProgress = Math.min(
85, const now = Date.now();
Math.round((charsReceived / EXPECTED_CHARS) * 75 + 10), if (now - lastEmitTime >= THROTTLE_MS) {
); const ratio = Math.min(1, charsReceived / expectedChars);
onProgress('llm', llmProgress, 'Конвертация через LLM...'); const llmProgress = Math.min(
LLM_PROGRESS_MAX,
Math.round(ratio * LLM_PROGRESS_RANGE + LLM_PROGRESS_MIN),
);
onProgress('llm', llmProgress, 'Конвертация через LLM...');
lastEmitTime = now;
}
} }
} }
onProgress('llm', LLM_PROGRESS_MAX, 'LLM завершил, обработка результата...');
const content = accumulated.trim(); const content = accumulated.trim();
if (!content) { if (!content) {
return { return {