Skip to content

Commit

Permalink
Integrate AI prompt with chatgpt 3.5 for PRO users (#481)
Browse files Browse the repository at this point in the history
* Add OpenAI library with initial implementation and configuration

* Fixed AI response handling issue

* removed unwanted packages

* Refactor response validation logic for improved accuracy

* Update build process and ESLint configuration; remove obsolete files and add new dependencies
  • Loading branch information
dharmesh-hemaram authored Nov 22, 2024
1 parent 3168ff4 commit 8b3abb0
Show file tree
Hide file tree
Showing 21 changed files with 315 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
echo "HEAD: ${{ env.NX_HEAD }}"
- run: npm ci
- name: Build Projects and Library
run: npx nx run-many -t build -p acf-options-page acf-extension --prod --base-href ${{vars.PUBLIC_URL}} --verbose
run: npx nx run-many -t build -p acf-options-page acf-extension --prod --base-href ${{vars.PUBLIC_URL}} --verbose --skip-nx-cache
env:
NX_PUBLIC_NAME: ${{vars.NX_PUBLIC_NAME}}
NX_PUBLIC_VARIANT: ${{vars.NX_PUBLIC_VARIANT}}
Expand Down
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
"eslint.validate": ["json"],
"[html]": {
"editor.formatOnSave": false
},
"sonarlint.connectedMode.project": {
"connectionId": "dhruv-techapps",
"projectKey": "Dhruv-Techapps_auto-clicker-auto-fill"
}
}
2 changes: 2 additions & 0 deletions apps/acf-extension/src/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { GoogleOauth2Background, RUNTIME_MESSAGE_GOOGLE_OAUTH } from '@dhruv-tec
import { GoogleSheetsBackground, RUNTIME_MESSAGE_GOOGLE_SHEETS } from '@dhruv-techapps/google-sheets';
import { registerNotifications } from '@dhruv-techapps/notifications';
import { RUNTIME_MESSAGE_VISION, VisionBackground } from '@dhruv-techapps/vision';
import { OpenAIBackground, RUNTIME_MESSAGE_OPENAI } from '@dhruv.techapps/openai';
import XMLHttpRequest from 'xhr-shim';
import { ACTION_POPUP } from '../common/constant';
import { DISCORD_CLIENT_ID, EDGE_OAUTH_CLIENT_ID, FIREBASE_FUNCTIONS_URL, OPTIONS_PAGE_URL, VARIANT } from '../common/environments';
Expand Down Expand Up @@ -72,6 +73,7 @@ try {
[RUNTIME_MESSAGE_FIREBASE_FIRESTORE]: new FirebaseFirestoreBackground(auth, EDGE_OAUTH_CLIENT_ID, OPTIONS_PAGE_URL),
[RUNTIME_MESSAGE_FIREBASE_FUNCTIONS]: new FirebaseFunctionsBackground(auth, FIREBASE_FUNCTIONS_URL, EDGE_OAUTH_CLIENT_ID),
[RUNTIME_MESSAGE_VISION]: new VisionBackground(auth, FIREBASE_FUNCTIONS_URL, EDGE_OAUTH_CLIENT_ID),
[RUNTIME_MESSAGE_OPENAI]: new OpenAIBackground(auth, FIREBASE_FUNCTIONS_URL, EDGE_OAUTH_CLIENT_ID),
};
Runtime.onMessageExternal(onMessageListener);
Runtime.onMessage(onMessageListener);
Expand Down
61 changes: 45 additions & 16 deletions apps/acf-extension/src/content_scripts/util/acf-value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,68 @@ import { Value } from '@dhruv-techapps/acf-util';
import { GoogleSheetsValue } from '@dhruv-techapps/google-sheets';
import { SandboxValue } from '@dhruv-techapps/sandbox';
import { VisionService, VisionValue } from '@dhruv-techapps/vision';
import { OpenAIService } from '@dhruv.techapps/openai';
import Common from '../common';

export const VALUE_MATCHER = {
GOOGLE_SHEETS: /^GoogleSheets::/i,
FUNC: /^Func::/i,
IMAGE: /^Image::/i,
OPENAI: /^OpenAI::/i,
};

export class ACFValue {
static async getValue(value: string, settings?: ActionSettings): Promise<string> {
value = await Value.getValue(value);
if (VALUE_MATCHER.GOOGLE_SHEETS.test(value)) {
value = GoogleSheetsValue.getSheetValue(value);
return this.getGoogleSheetsValue(value);
}
if (VALUE_MATCHER.FUNC.test(value)) {
value = await SandboxValue.getFuncValue(value);
return this.getFuncValue(value);
}
if (VALUE_MATCHER.OPENAI.test(value)) {
return this.getOpenAIValue(value);
}
if (VALUE_MATCHER.IMAGE.test(value)) {
try {
const elementFinder = value.replace(/image::/i, '');
const elements = await Common.start(elementFinder, settings);
if (elements === undefined || typeof elements === 'number' || elements.length === 0) {
throw new Error('No element found with the given selector');
}
const data = VisionValue.getImageSrc(elements);
value = await VisionService.imagesAnnotate(data);
return value;
} catch (error) {
if (error instanceof Error) {
return error.message;
}
return this.getImageValue(value, settings);
}
return value;
}

private static getGoogleSheetsValue(value: string): string {
return GoogleSheetsValue.getSheetValue(value);
}

private static async getFuncValue(value: string): Promise<string> {
return await SandboxValue.getFuncValue(value);
}

private static async getOpenAIValue(value: string): Promise<string> {
try {
const prompt = value.replace(/openai::/i, '');
const message = await OpenAIService.generateText({ content: prompt });
return message;
} catch (error) {
if (error instanceof Error) {
return error.message;
}
}
return value;
}

private static async getImageValue(value: string, settings?: ActionSettings): Promise<string> {
try {
const elementFinder = value.replace(/image::/i, '');
const elements = await Common.start(elementFinder, settings);
if (elements === undefined || typeof elements === 'number' || elements.length === 0) {
throw new Error('No element found with the given selector');
}
const data = VisionValue.getImageSrc(elements);
return await VisionService.imagesAnnotate(data);
} catch (error) {
if (error instanceof Error) {
return error.message;
}
return value;
}
return value;
}
Expand Down
5 changes: 5 additions & 0 deletions apps/acf-options-page/src/components/data-list.components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ export function DataList() {
<option value='Image::Name::'>Image::Name::</option>
<option value='Image::Selector::'>Image::Selector::</option>
<option value='Image:://input[@id="element-id"]'>Image:://input[@id=&quot;element-id&quot;]</option>
<option value='openai::your prompt'>openai::your prompt</option>
{/*<option value='openai::summarizeText'>openai::summarizeText</option>
<option value='openai::translateText'>openai::translateText</option>
<option value='openai::classifyText'>openai::classifyText</option>
<option value='openai::analyzeSentiment'>openai::analyzeSentiment</option>*/}
</datalist>
<datalist id='valueExtractor'>
<option value='@id'>To get id attribute of element</option>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ export class FirebaseFunctionsBackground extends FirebaseOauth2Background {
const response = await this.#fetch(url, headers, data);
return response;
}
async openAiChat<Req, Res>(data: Req): Promise<Res> {
const headers = await this._getFirebaseHeaders();
const url = new URL(this.cloudFunctionUrl + '/openAiChat');
const response = await this.#fetch(url, headers, data);
return response;
}

async getValues<Req, Res>(data: Req): Promise<Res> {
const headers = await this._getFirebaseHeaders([GOOGLE_SCOPES.SHEETS]);
Expand Down
25 changes: 25 additions & 0 deletions libs/shared/openai/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"extends": ["../../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/dependency-checks": "error"
}
}
]
}
11 changes: 11 additions & 0 deletions libs/shared/openai/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# openai

This library was generated with [Nx](https://nx.dev).

## Building

Run `nx build openai` to build the library.

## Running unit tests

Run `nx test openai` to execute the unit tests via [Jest](https://jestjs.io).
10 changes: 10 additions & 0 deletions libs/shared/openai/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default {
displayName: 'openai',
preset: '../../../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../../coverage/libs/shared/openai',
};
12 changes: 12 additions & 0 deletions libs/shared/openai/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "@dhruv.techapps/openai",
"dependencies": {
"tslib": "^2.3.0",
"@dhruv-techapps/core-common": "*",
"@dhruv-techapps/core-service": "*",
"@dhruv-techapps/firebase-functions": "*"
},
"type": "commonjs",
"main": "./src/index.js",
"typings": "./src/index.d.ts"
}
42 changes: 42 additions & 0 deletions libs/shared/openai/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "openai",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/shared/openai/src",
"projectType": "library",
"release": {
"version": {
"generatorOptions": {
"packageRoot": "dist/{projectRoot}",
"currentVersionResolver": "git-tag"
}
}
},
"tags": ["shared"],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/shared/openai",
"main": "libs/shared/openai/src/index.ts",
"tsConfig": "libs/shared/openai/tsconfig.lib.json",
"assets": ["libs/shared/openai/*.md"]
}
},
"nx-release-publish": {
"options": {
"packageRoot": "dist/{projectRoot}"
}
},
"lint": {
"executor": "@nx/eslint:lint"
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/shared/openai/jest.config.ts"
}
}
}
}
4 changes: 4 additions & 0 deletions libs/shared/openai/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './lib/openai-background';
export * from './lib/openai.constant';
export * from './lib/openai.service';
export * from './lib/openai.types';
13 changes: 13 additions & 0 deletions libs/shared/openai/src/lib/openai-background.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { FirebaseFunctionsBackground } from '@dhruv-techapps/firebase-functions';
import { OpenAIRequest, OpenAIResponse } from './openai.types';

export class OpenAIBackground extends FirebaseFunctionsBackground {
async generateText({ content }: OpenAIRequest): Promise<string> {
if (!content || content.trim().length === 0) {
throw new Error('No prompt provided');
}
const data: OpenAIRequest = { content };
const result = await this.openAiChat<OpenAIRequest, OpenAIResponse>(data);
return result.content;
}
}
1 change: 1 addition & 0 deletions libs/shared/openai/src/lib/openai.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const RUNTIME_MESSAGE_OPENAI = 'openai';
14 changes: 14 additions & 0 deletions libs/shared/openai/src/lib/openai.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { RuntimeMessageRequest } from '@dhruv-techapps/core-common';
import { CoreService } from '@dhruv-techapps/core-service';
import { RUNTIME_MESSAGE_OPENAI } from './openai.constant';
import { OpenAIRequest } from './openai.types';

export class OpenAIService extends CoreService {
static async generateText(message: OpenAIRequest): Promise<string> {
return await this.message<RuntimeMessageRequest<OpenAIRequest>, string>({
messenger: RUNTIME_MESSAGE_OPENAI,
methodName: 'generateText',
message: message,
});
}
}
7 changes: 7 additions & 0 deletions libs/shared/openai/src/lib/openai.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type OpenAIRequest = {
content: string;
};

export type OpenAIResponse = {
content: string;
};
22 changes: 22 additions & 0 deletions libs/shared/openai/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}
10 changes: 10 additions & 0 deletions libs/shared/openai/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
}
9 changes: 9 additions & 0 deletions libs/shared/openai/tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
}
Loading

0 comments on commit 8b3abb0

Please sign in to comment.