Revert "[js/rn] support load model from buffer on Android (#12676)" (#13903)

### Description
<!-- Describe your changes. -->

As title.

This pr is missing an un-updated index.android.gradle, which causing an
unstable e2e unit test run for React Native CI.

Revert the changes for now.

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->

To unblock Ort React Native CI pipeline failure.
This commit is contained in:
Rachel Guo 2022-12-09 11:05:54 -08:00 committed by GitHub
parent d22be84add
commit dead5c6b3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 98 deletions

View file

@ -15,7 +15,6 @@ import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -47,31 +46,18 @@ public class OnnxruntimeModuleTest {
when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray());
OnnxruntimeModule ortModule = new OnnxruntimeModule(reactContext);
String sessionKey = "";
// test loadModel()
{
InputStream modelStream =
reactContext.getResources().openRawResource(ai.onnxruntime.reactnative.test.R.raw.test_types_float);
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len;
while ((len = modelStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
byte[] modelBuffer = byteBuffer.toByteArray();
JavaOnlyMap options = new JavaOnlyMap();
try {
ReadableMap resultMap = ortModule.loadModel(modelBuffer, options);
sessionKey = resultMap.getString("key");
ReadableMap resultMap = ortModule.loadModel("test", modelStream, options);
ReadableArray inputNames = resultMap.getArray("inputNames");
ReadableArray outputNames = resultMap.getArray("outputNames");
Assert.assertEquals(resultMap.getString("key"), "test");
Assert.assertEquals(inputNames.size(), 1);
Assert.assertEquals(inputNames.getString(0), "input");
Assert.assertEquals(outputNames.size(), 1);
@ -117,7 +103,7 @@ public class OnnxruntimeModuleTest {
options.putBoolean("encodeTensorData", true);
try {
ReadableMap resultMap = ortModule.run(sessionKey, inputDataMap, outputNames, options);
ReadableMap resultMap = ortModule.run("test", inputDataMap, outputNames, options);
ReadableMap outputMap = resultMap.getMap("output");
for (int i = 0; i < 2; ++i) {

View file

@ -13,7 +13,6 @@ import ai.onnxruntime.OrtSession.RunOptions;
import ai.onnxruntime.OrtSession.SessionOptions;
import android.net.Uri;
import android.os.Build;
import android.util.Base64;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
@ -32,7 +31,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -48,13 +46,6 @@ public class OnnxruntimeModule extends ReactContextBaseJavaModule {
private static OrtEnvironment ortEnvironment = OrtEnvironment.getEnvironment();
private static Map<String, OrtSession> sessionMap = new HashMap<>();
private static BigInteger nextSessionId = new BigInteger("0");
private static String getNextSessionKey() {
String key = nextSessionId.toString();
nextSessionId = nextSessionId.add(BigInteger.valueOf(1));
return key;
}
public OnnxruntimeModule(ReactApplicationContext context) {
super(context);
reactContext = context;
@ -69,11 +60,11 @@ public class OnnxruntimeModule extends ReactContextBaseJavaModule {
/**
* React native binding API to load a model using given uri.
*
* @param uri a model file location
* @param uri a model file location. it's used as a key when multiple sessions are created, i.e. multiple models are
* loaded.
* @param options onnxruntime session options
* @param promise output returning back to react native js
* @note the value provided to `promise` includes a key representing the session.
* when run() is called, the key must be passed into the first parameter.
* @note when run() is called, the same uri must be passed into the first parameter.
*/
@ReactMethod
public void loadModel(String uri, ReadableMap options, Promise promise) {
@ -85,30 +76,10 @@ public class OnnxruntimeModule extends ReactContextBaseJavaModule {
}
}
/**
* React native binding API to load a model using the BASE64 encoded model data.
*
* @param data the BASE64 encoded model data.
* @param options onnxruntime session options
* @param promise output returning back to react native js
* @note the value provided to `promise` includes a key representing the session.
* when run() is called, the key must be passed into the first parameter.
*/
@ReactMethod
public void loadModelFromBase64EncodedBuffer(String data, ReadableMap options, Promise promise) {
try {
byte[] modelData = Base64.decode(data, Base64.DEFAULT);
WritableMap resultMap = loadModel(modelData, options);
promise.resolve(resultMap);
} catch (Exception e) {
promise.reject("Can't load model from buffer: " + e.getMessage(), e);
}
}
/**
* React native binding API to run a model using given uri.
*
* @param key session key representing a session given at loadModel()
* @param key a model file location given at loadModel()
* @param input an input tensor
* @param output an output names to be returned
* @param options onnxruntime run options
@ -132,49 +103,39 @@ public class OnnxruntimeModule extends ReactContextBaseJavaModule {
* @return model loading information, such as key, input names, and output names
*/
public WritableMap loadModel(String uri, ReadableMap options) throws Exception {
return loadModelImpl(uri, null, options);
InputStream modelStream = reactContext.getApplicationContext().getContentResolver().openInputStream(Uri.parse(uri));
WritableMap resultMap = loadModel(uri, modelStream, options);
modelStream.close();
return resultMap;
}
/**
* Load a model from buffer.
* Load a model from raw resource directory.
*
* @param modelData the model data buffer
* @param uri uri parameter from react native loadModel() or dummy string for unit testing purpose
* @param modelStream a input stream to read a model
* @param options onnxruntime session options
* @return model loading information, such as key, input names, and output names
*/
public WritableMap loadModel(byte[] modelData, ReadableMap options) throws Exception {
return loadModelImpl("", modelData, options);
}
public WritableMap loadModel(String uri, InputStream modelStream, ReadableMap options) throws Exception {
OrtSession ortSession = null;
/**
* Load model implementation method for either from model path or model data buffer.
*
* @param uri uri parameter from react native loadModel()
* @param modelData model data buffer
* @param options onnxruntime session options
* @return model loading information map, such as key, input names, and output names
*/
private WritableMap loadModelImpl(String uri, byte[] modelData, ReadableMap options) throws Exception {
OrtSession ortSession;
SessionOptions sessionOptions = parseSessionOptions(options);
if (!sessionMap.containsKey(uri)) {
byte[] modelArray = null;
if (modelData != null && modelData.length > 0) { // load model via model data array
ortSession = ortEnvironment.createSession(modelData, sessionOptions);
} else { // load model via model path string uri
InputStream modelStream =
reactContext.getApplicationContext().getContentResolver().openInputStream(Uri.parse(uri));
Reader reader = new BufferedReader(new InputStreamReader(modelStream));
byte[] modelArray = new byte[modelStream.available()];
modelArray = new byte[modelStream.available()];
modelStream.read(modelArray);
modelStream.close();
SessionOptions sessionOptions = parseSessionOptions(options);
ortSession = ortEnvironment.createSession(modelArray, sessionOptions);
sessionMap.put(uri, ortSession);
} else {
ortSession = sessionMap.get(uri);
}
String key = getNextSessionKey();
sessionMap.put(key, ortSession);
WritableMap resultMap = Arguments.createMap();
resultMap.putString("key", key);
resultMap.putString("key", uri);
WritableArray inputNames = Arguments.createArray();
for (String inputName : ortSession.getInputNames()) {
inputNames.pushString(inputName);
@ -192,7 +153,7 @@ public class OnnxruntimeModule extends ReactContextBaseJavaModule {
/**
* Run a model using given uri.
*
* @param key a session key representing the session given at loadModel()
* @param key a model file location given at loadModel()
* @param input an input tensor
* @param output an output names to be returned
* @param options onnxruntime run options
@ -201,7 +162,7 @@ public class OnnxruntimeModule extends ReactContextBaseJavaModule {
public WritableMap run(String key, ReadableMap input, ReadableArray output, ReadableMap options) throws Exception {
OrtSession ortSession = sessionMap.get(key);
if (ortSession == null) {
throw new Exception("Model is not loaded.");
throw new Exception("Model is not loaded: " + key);
}
RunOptions runOptions = parseRunOptions(options);

View file

@ -48,35 +48,25 @@ class OnnxruntimeSessionHandler implements SessionHandler {
#inferenceSession: Binding.InferenceSession;
#key: string;
#pathOrBuffer: string|Uint8Array;
inputNames: string[];
outputNames: string[];
constructor(pathOrBuffer: string|Uint8Array) {
constructor(path: string) {
this.#inferenceSession = binding;
this.#pathOrBuffer = pathOrBuffer;
this.#key = '';
this.#key = normalizePath(path);
this.inputNames = [];
this.outputNames = [];
}
async loadModel(options: InferenceSession.SessionOptions): Promise<void> {
try {
let results: Binding.ModelLoadInfoType;
// load a model
if (typeof this.#pathOrBuffer === 'string') {
results = await this.#inferenceSession.loadModel(normalizePath(this.#pathOrBuffer), options);
} else {
if (!this.#inferenceSession.loadModelFromBase64EncodedBuffer) {
throw new Error('Native module method "loadModelFromBase64EncodedBuffer" is not defined');
}
const modelInBase64String = Buffer.from(this.#pathOrBuffer).toString('base64');
results = await this.#inferenceSession.loadModelFromBase64EncodedBuffer(modelInBase64String, options);
}
const results: Binding.ModelLoadInfoType = await this.#inferenceSession.loadModel(this.#key, options);
// resolve promise if onnxruntime session is successfully created
this.#key = results.key;
if (results.key !== this.#key) {
throw new Error('Session key is invalid');
}
this.inputNames = results.inputNames;
this.outputNames = results.outputNames;
} catch (e) {
@ -166,6 +156,9 @@ class OnnxruntimeBackend implements Backend {
async createSessionHandler(pathOrBuffer: string|Uint8Array, options?: InferenceSession.SessionOptions):
Promise<SessionHandler> {
if (typeof pathOrBuffer !== 'string') {
throw new Error('Uint8Array is not supported');
}
const handler = new OnnxruntimeSessionHandler(pathOrBuffer);
await handler.loadModel(options || {});
return handler;

View file

@ -64,7 +64,6 @@ export declare namespace Binding {
interface InferenceSession {
loadModel(modelPath: string, options: SessionOptions): Promise<ModelLoadInfoType>;
loadModelFromBase64EncodedBuffer?(buffer: string, options: SessionOptions): Promise<ModelLoadInfoType>;
run(key: string, feeds: FeedsType, fetches: FetchesType, options: RunOptions): Promise<ReturnType>;
}
}