Skip to content

feat: Hookless API#82

Merged
jakmro merged 15 commits intomainfrom
@jakmro/hookless-api
Jan 27, 2025
Merged

feat: Hookless API#82
jakmro merged 15 commits intomainfrom
@jakmro/hookless-api

Conversation

@jakmro
Copy link
Copy Markdown
Contributor

@jakmro jakmro commented Jan 14, 2025

Description

This PR introduces hookless API and restructures the ./src directory.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update (improves or adds clarity to existing documentation)

Tested on

  • iOS
  • Android

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings

@jakmro jakmro marked this pull request as ready for review January 20, 2025 09:30
@jakmro jakmro changed the title feat: Hookless API draft: feat: Hookless API Jan 21, 2025
@jakmro jakmro changed the title draft: feat: Hookless API feat: Hookless API Jan 21, 2025
@jakmro jakmro marked this pull request as draft January 21, 2025 08:40
@jakmro jakmro marked this pull request as ready for review January 21, 2025 11:25
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we changing it, UseClassification as a name for a type doesn't seem too clear for me

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes were made to avoid name conflicts with the new classes introduced in this PR.

score: number;
}

interface ObjectDetectionModule {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

<summary>Type definitions</summary>

```typescript
interface StyleTransferModule {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Comment thread src/modules/general/ExecutorchModule.ts Outdated
import { ETInput, getTypeIdentifier } from '../../types/common';

export class ExecutorchModule {
static async load(modelSource: string) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we use load function from BaseModule here?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jakmro To do this let's craete BaseModule in src/modules/BaseModule.ts liek so:

export class BaseModule {
  static module:
    | _StyleTransferModule
    | _ObjectDetectionModule
    | _ClassificationModule
    | _ETModule;
  
  static async load(modelSource: string | number) {
    if (!modelSource) return;

    let path = typeof modelSource === 'number' ? Image.resolveAssetSource(modelSource).uri : modelSource;

    try {
      await this.module.loadModule(path as string);
    } catch (e) {
      throw new Error(getError(e));
    }
  }

  static async forward(..._: any[]): Promise<any> {
    throw new Error("Method 'myMethod()' must be implemented.");
  }
}

and then just extend both ExecutorchModule and BaseCVModule.
The change in let path is necessary for typescript to correctly infer path type as string.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I think we should use type ResourceSource like in LLMModule

@@ -72,44 +72,44 @@ const StyleTransfer = StyleTransferSpec
);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep it as it was if we ever want to create separate instances per call instead of treating each module as singleton.

import { Image } from 'react-native';
import { getError } from '../../Error';

export class BaseModule {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export class BaseModule {
export class BaseCVModule {

Comment thread src/modules/general/ExecutorchModule.ts Outdated
Comment thread src/modules/general/ExecutorchModule.ts Outdated
}

try {
await _ETModule.loadModule(path);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
await _ETModule.loadModule(path);
await this.module.loadModule(path);

Comment thread src/modules/general/ExecutorchModule.ts Outdated

try {
const numberArray = [...input] as number[];
return await _ETModule.forward(numberArray, shape, inputType);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return await _ETModule.forward(numberArray, shape, inputType);
return await this.module.forward(numberArray, shape, inputType);

}: Props): StyleTransferModule => {
const [module, _] = useState(() => new _StyleTransferModule());
export const useStyleTransfer = ({ modelSource }: Props): UseStyleTransfer => {
const [module, _] = useState(() => _StyleTransferModule);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like above

}

interface ClassificationModule {
interface UseClassification {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's remove this naming completely and move this as inline type below. This would solve naming issues as well as give end user more clarity of what the type actually is instead of it being a cryptic UseClassification

}

interface ObjectDetectionModule {
interface UseObjectDetection {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like above

}

interface StyleTransferModule {
interface UseStyleTransfer {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like above

@@ -72,44 +72,44 @@ const StyleTransfer = StyleTransferSpec
);

class _ObjectDetectionModule {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's propagate return types from turbo modules specs like so:

Suggested change
class _ObjectDetectionModule {
class _ObjectDetectionModule {
static async forward(input: string) : ReturnType<ObjectDetectionInterface["forward"]> {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import { Spec as ObjectDetectionInterface } from './NativeObjectDetection';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do this for all methods for other classes in this file too.

@jakmro jakmro requested a review from mkopcins January 23, 2025 10:07
Comment on lines +17 to +30
let modelUrl = modelSource;
let tokenizerUrl = tokenizerSource;

if (typeof modelSource === 'number') {
modelUrl = Image.resolveAssetSource(modelSource).uri;
}

if (typeof tokenizerSource === 'number') {
tokenizerUrl = Image.resolveAssetSource(tokenizerSource).uri;
}

await LLM.loadLLM(
modelUrl as string,
tokenizerUrl as string,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let modelUrl = modelSource;
let tokenizerUrl = tokenizerSource;
if (typeof modelSource === 'number') {
modelUrl = Image.resolveAssetSource(modelSource).uri;
}
if (typeof tokenizerSource === 'number') {
tokenizerUrl = Image.resolveAssetSource(tokenizerSource).uri;
}
await LLM.loadLLM(
modelUrl as string,
tokenizerUrl as string,
let modelUrl = typeof modelSource === 'number' ? Image.resolveAssetSource(modelSource).uri : modelSource;
let tokenizerUrl = typeof tokenizerSource === 'number' ? Image.resolveAssetSource(tokenizerSource).uri : tokenizerSource;
await LLM.loadLLM(
modelUrl,
tokenizerUrl,

This allows typescript to infer types correctly

@jakmro jakmro merged commit cbe2b55 into main Jan 27, 2025
@jakmro jakmro deleted the @jakmro/hookless-api branch January 27, 2025 09:45
mkopcins pushed a commit that referenced this pull request Oct 15, 2025
## Description
This PR introduces hookless API and restructures the `./src` directory.

### Type of change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Documentation update (improves or adds clarity to existing
documentation)

### Tested on
- [x] iOS
- [x] Android

### Checklist
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly
- [x] My changes generate no new warnings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants