generateEmbedding method
Generate embedding for text via Ollama with retry logic
Implementation
Future<List<double>> generateEmbedding(String text) async {
const maxRetries = 3;
const retryDelay = Duration(seconds: 3);
// Log text size for debugging (only if text is large)
if (text.length > 10000) {
_logger.fine('📏 Large text chunk: ${text.length} characters');
}
for (var attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await _generateEmbeddingOnce(text);
} catch (e) {
// Re-throw ModelNotFoundException immediately (no retry)
if (e is ModelNotFoundException) {
rethrow;
}
// Check if it's a retryable error
final isRetryable = _isRetryableError(e);
if (attempt < maxRetries && isRetryable) {
// Check if it's a "llama runner process" error - needs longer delay
final errorStr = e.toString().toLowerCase();
final isRunnerError = errorStr.contains('llama runner process') ||
errorStr.contains('no longer running');
// Wait before retry with exponential backoff
// Longer delay for runner errors
final baseDelay = isRunnerError
? Duration(seconds: retryDelay.inSeconds * 2)
: retryDelay;
final delay =
Duration(milliseconds: baseDelay.inMilliseconds * attempt);
final errorPreview = e.toString().length > 150
? '${e.toString().substring(0, 150)}...'
: e.toString();
_logger.warning(
'⚠️ Attempt $attempt of $maxRetries failed, retrying in ${delay.inSeconds}s: $errorPreview',
);
await Future.delayed(delay);
_logger.info('🔄 Retrying attempt $attempt of $maxRetries...');
continue;
}
// Last attempt or non-retryable error - rethrow
if (attempt >= maxRetries) {
final errorStr = e.toString().toLowerCase();
final isEofError =
errorStr.contains('eof') || errorStr.contains('connection');
_logger.severe(
'❌ All $maxRetries attempts exhausted. Last error: $e '
'(text size: ${text.length} chars)',
);
if (isEofError) {
_logger.warning(
'💡 Tip: EOF errors often indicate Ollama server instability. '
'Try restarting Ollama: ollama serve',
);
}
}
rethrow;
}
}
// This should never be reached, but just in case
throw Exception('Failed to generate embedding after $maxRetries attempts');
}