@rajeev02/edge-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +15 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +25 -0
- package/lib/index.js.map +1 -0
- package/lib/ocr/index.d.ts +82 -0
- package/lib/ocr/index.d.ts.map +1 -0
- package/lib/ocr/index.js +106 -0
- package/lib/ocr/index.js.map +1 -0
- package/lib/pipeline/index.d.ts +69 -0
- package/lib/pipeline/index.d.ts.map +1 -0
- package/lib/pipeline/index.js +69 -0
- package/lib/pipeline/index.js.map +1 -0
- package/lib/voice/index.d.ts +57 -0
- package/lib/voice/index.d.ts.map +1 -0
- package/lib/voice/index.js +94 -0
- package/lib/voice/index.js.map +1 -0
- package/package.json +52 -0
- package/src/index.ts +45 -0
- package/src/ocr/index.ts +168 -0
- package/src/pipeline/index.ts +119 -0
- package/src/voice/index.ts +139 -0
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rajeev02/edge-ai
|
|
3
|
+
* Edge AI / On-Device ML Toolkit
|
|
4
|
+
* OCR, face detection, voice commands, document scanning
|
|
5
|
+
*
|
|
6
|
+
* @author Rajeev Kumar Joshi
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
export { ModelManager } from "./pipeline";
|
|
10
|
+
export type { ModelConfig, InferenceResult, BoundingBox, MLBackend, ModelState, } from "./pipeline";
|
|
11
|
+
export { detectDocumentType, extractAadhaarNumber, extractPanNumber, validatePan, validateAadhaar, getScanningTips, } from "./ocr";
|
|
12
|
+
export type { OcrResult, OcrBlock, AadhaarCardData, PanCardData, DrivingLicenseData, DocumentType, } from "./ocr";
|
|
13
|
+
export { parseVoiceIntent, getTtsConfig, SUPPORTED_VOICE_LANGUAGES, } from "./voice";
|
|
14
|
+
export type { VoiceConfig, SpeechResult, VoiceIntent, VoiceState, } from "./voice";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EACV,WAAW,EACX,eAAe,EACf,WAAW,EACX,SAAS,EACT,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,eAAe,EACf,eAAe,GAChB,MAAM,OAAO,CAAC;AACf,YAAY,EACV,SAAS,EACT,QAAQ,EACR,eAAe,EACf,WAAW,EACX,kBAAkB,EAClB,YAAY,GACb,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,yBAAyB,GAC1B,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,GACX,MAAM,SAAS,CAAC"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SUPPORTED_VOICE_LANGUAGES = exports.getTtsConfig = exports.parseVoiceIntent = exports.getScanningTips = exports.validateAadhaar = exports.validatePan = exports.extractPanNumber = exports.extractAadhaarNumber = exports.detectDocumentType = exports.ModelManager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @rajeev02/edge-ai
|
|
6
|
+
* Edge AI / On-Device ML Toolkit
|
|
7
|
+
* OCR, face detection, voice commands, document scanning
|
|
8
|
+
*
|
|
9
|
+
* @author Rajeev Kumar Joshi
|
|
10
|
+
* @license MIT
|
|
11
|
+
*/
|
|
12
|
+
var pipeline_1 = require("./pipeline");
|
|
13
|
+
Object.defineProperty(exports, "ModelManager", { enumerable: true, get: function () { return pipeline_1.ModelManager; } });
|
|
14
|
+
var ocr_1 = require("./ocr");
|
|
15
|
+
Object.defineProperty(exports, "detectDocumentType", { enumerable: true, get: function () { return ocr_1.detectDocumentType; } });
|
|
16
|
+
Object.defineProperty(exports, "extractAadhaarNumber", { enumerable: true, get: function () { return ocr_1.extractAadhaarNumber; } });
|
|
17
|
+
Object.defineProperty(exports, "extractPanNumber", { enumerable: true, get: function () { return ocr_1.extractPanNumber; } });
|
|
18
|
+
Object.defineProperty(exports, "validatePan", { enumerable: true, get: function () { return ocr_1.validatePan; } });
|
|
19
|
+
Object.defineProperty(exports, "validateAadhaar", { enumerable: true, get: function () { return ocr_1.validateAadhaar; } });
|
|
20
|
+
Object.defineProperty(exports, "getScanningTips", { enumerable: true, get: function () { return ocr_1.getScanningTips; } });
|
|
21
|
+
var voice_1 = require("./voice");
|
|
22
|
+
Object.defineProperty(exports, "parseVoiceIntent", { enumerable: true, get: function () { return voice_1.parseVoiceIntent; } });
|
|
23
|
+
Object.defineProperty(exports, "getTtsConfig", { enumerable: true, get: function () { return voice_1.getTtsConfig; } });
|
|
24
|
+
Object.defineProperty(exports, "SUPPORTED_VOICE_LANGUAGES", { enumerable: true, get: function () { return voice_1.SUPPORTED_VOICE_LANGUAGES; } });
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACH,uCAA0C;AAAjC,wGAAA,YAAY,OAAA;AASrB,6BAOe;AANb,yGAAA,kBAAkB,OAAA;AAClB,2GAAA,oBAAoB,OAAA;AACpB,uGAAA,gBAAgB,OAAA;AAChB,kGAAA,WAAW,OAAA;AACX,sGAAA,eAAe,OAAA;AACf,sGAAA,eAAe,OAAA;AAWjB,iCAIiB;AAHf,yGAAA,gBAAgB,OAAA;AAChB,qGAAA,YAAY,OAAA;AACZ,kHAAA,yBAAyB,OAAA"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rajeev02/edge-ai — OCR Module
|
|
3
|
+
* On-device text recognition, document scanning, Indian ID card extraction
|
|
4
|
+
*/
|
|
5
|
+
export interface OcrResult {
|
|
6
|
+
/** Full recognized text */
|
|
7
|
+
text: string;
|
|
8
|
+
/** Individual text blocks with positions */
|
|
9
|
+
blocks: OcrBlock[];
|
|
10
|
+
/** Detected language(s) */
|
|
11
|
+
languages: string[];
|
|
12
|
+
/** Overall confidence (0-1) */
|
|
13
|
+
confidence: number;
|
|
14
|
+
/** Processing time in ms */
|
|
15
|
+
processingTimeMs: number;
|
|
16
|
+
}
|
|
17
|
+
export interface OcrBlock {
|
|
18
|
+
text: string;
|
|
19
|
+
boundingBox: {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
};
|
|
25
|
+
confidence: number;
|
|
26
|
+
language?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Extracted data from Indian ID cards */
|
|
29
|
+
export interface AadhaarCardData {
|
|
30
|
+
name?: string;
|
|
31
|
+
aadhaarNumber?: string;
|
|
32
|
+
dateOfBirth?: string;
|
|
33
|
+
gender?: string;
|
|
34
|
+
address?: string;
|
|
35
|
+
pincode?: string;
|
|
36
|
+
photo?: string;
|
|
37
|
+
confidence: number;
|
|
38
|
+
}
|
|
39
|
+
export interface PanCardData {
|
|
40
|
+
name?: string;
|
|
41
|
+
panNumber?: string;
|
|
42
|
+
fatherName?: string;
|
|
43
|
+
dateOfBirth?: string;
|
|
44
|
+
confidence: number;
|
|
45
|
+
}
|
|
46
|
+
export interface DrivingLicenseData {
|
|
47
|
+
name?: string;
|
|
48
|
+
licenseNumber?: string;
|
|
49
|
+
dateOfBirth?: string;
|
|
50
|
+
validity?: string;
|
|
51
|
+
address?: string;
|
|
52
|
+
vehicleClasses?: string[];
|
|
53
|
+
confidence: number;
|
|
54
|
+
}
|
|
55
|
+
export type DocumentType = "aadhaar_front" | "aadhaar_back" | "pan" | "driving_license" | "voter_id" | "passport" | "unknown";
|
|
56
|
+
/**
|
|
57
|
+
* Detect the type of Indian ID document from OCR text
|
|
58
|
+
*/
|
|
59
|
+
export declare function detectDocumentType(ocrText: string): DocumentType;
|
|
60
|
+
/**
|
|
61
|
+
* Extract Aadhaar number from OCR text
|
|
62
|
+
* Returns masked format: XXXX XXXX 1234
|
|
63
|
+
*/
|
|
64
|
+
export declare function extractAadhaarNumber(text: string): string | null;
|
|
65
|
+
/**
|
|
66
|
+
* Extract PAN number from OCR text
|
|
67
|
+
* Format: ABCDE1234F
|
|
68
|
+
*/
|
|
69
|
+
export declare function extractPanNumber(text: string): string | null;
|
|
70
|
+
/**
|
|
71
|
+
* Validate PAN number format
|
|
72
|
+
*/
|
|
73
|
+
export declare function validatePan(pan: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Validate Aadhaar number (Verhoeff checksum)
|
|
76
|
+
*/
|
|
77
|
+
export declare function validateAadhaar(aadhaar: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Suggested document scanning tips for better OCR
|
|
80
|
+
*/
|
|
81
|
+
export declare function getScanningTips(docType: DocumentType): string[];
|
|
82
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ocr/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,SAAS;IACxB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,cAAc,GACd,KAAK,GACL,iBAAiB,GACjB,UAAU,GACV,UAAU,GACV,SAAS,CAAC;AAEd;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CA0BhE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAahE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,EAAE,CAwB/D"}
|
package/lib/ocr/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @rajeev02/edge-ai — OCR Module
|
|
4
|
+
* On-device text recognition, document scanning, Indian ID card extraction
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.detectDocumentType = detectDocumentType;
|
|
8
|
+
exports.extractAadhaarNumber = extractAadhaarNumber;
|
|
9
|
+
exports.extractPanNumber = extractPanNumber;
|
|
10
|
+
exports.validatePan = validatePan;
|
|
11
|
+
exports.validateAadhaar = validateAadhaar;
|
|
12
|
+
exports.getScanningTips = getScanningTips;
|
|
13
|
+
/**
|
|
14
|
+
* Detect the type of Indian ID document from OCR text
|
|
15
|
+
*/
|
|
16
|
+
function detectDocumentType(ocrText) {
|
|
17
|
+
const text = ocrText.toLowerCase();
|
|
18
|
+
if (text.includes("aadhaar") ||
|
|
19
|
+
text.includes("unique identification") ||
|
|
20
|
+
text.includes("uidai")) {
|
|
21
|
+
return text.includes("address") ? "aadhaar_back" : "aadhaar_front";
|
|
22
|
+
}
|
|
23
|
+
if (text.includes("income tax") || text.includes("permanent account"))
|
|
24
|
+
return "pan";
|
|
25
|
+
if (text.includes("driving") ||
|
|
26
|
+
text.includes("licence") ||
|
|
27
|
+
text.includes("motor vehicle"))
|
|
28
|
+
return "driving_license";
|
|
29
|
+
if (text.includes("election") ||
|
|
30
|
+
text.includes("voter") ||
|
|
31
|
+
text.includes("eci"))
|
|
32
|
+
return "voter_id";
|
|
33
|
+
if (text.includes("passport") || text.includes("republic of india"))
|
|
34
|
+
return "passport";
|
|
35
|
+
return "unknown";
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract Aadhaar number from OCR text
|
|
39
|
+
* Returns masked format: XXXX XXXX 1234
|
|
40
|
+
*/
|
|
41
|
+
function extractAadhaarNumber(text) {
|
|
42
|
+
const match = text.replace(/\s/g, "").match(/\d{12}/);
|
|
43
|
+
if (match) {
|
|
44
|
+
const num = match[0];
|
|
45
|
+
return `XXXX XXXX ${num.slice(8)}`;
|
|
46
|
+
}
|
|
47
|
+
// Try with spaces
|
|
48
|
+
const spaced = text.match(/\d{4}\s?\d{4}\s?\d{4}/);
|
|
49
|
+
if (spaced) {
|
|
50
|
+
const digits = spaced[0].replace(/\s/g, "");
|
|
51
|
+
return `XXXX XXXX ${digits.slice(8)}`;
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extract PAN number from OCR text
|
|
57
|
+
* Format: ABCDE1234F
|
|
58
|
+
*/
|
|
59
|
+
function extractPanNumber(text) {
|
|
60
|
+
const match = text.match(/[A-Z]{5}[0-9]{4}[A-Z]/);
|
|
61
|
+
return match ? match[0] : null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validate PAN number format
|
|
65
|
+
*/
|
|
66
|
+
function validatePan(pan) {
|
|
67
|
+
return /^[A-Z]{5}[0-9]{4}[A-Z]$/.test(pan);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Validate Aadhaar number (Verhoeff checksum)
|
|
71
|
+
*/
|
|
72
|
+
function validateAadhaar(aadhaar) {
|
|
73
|
+
const digits = aadhaar.replace(/\s/g, "");
|
|
74
|
+
if (digits.length !== 12 || !/^\d{12}$/.test(digits))
|
|
75
|
+
return false;
|
|
76
|
+
// Basic: first digit can't be 0 or 1
|
|
77
|
+
return digits[0] !== "0" && digits[0] !== "1";
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Suggested document scanning tips for better OCR
|
|
81
|
+
*/
|
|
82
|
+
function getScanningTips(docType) {
|
|
83
|
+
const common = [
|
|
84
|
+
"Place document on a flat, dark surface",
|
|
85
|
+
"Ensure good lighting without glare",
|
|
86
|
+
"Keep camera steady and parallel to document",
|
|
87
|
+
];
|
|
88
|
+
switch (docType) {
|
|
89
|
+
case "aadhaar_front":
|
|
90
|
+
case "aadhaar_back":
|
|
91
|
+
return [
|
|
92
|
+
...common,
|
|
93
|
+
"Ensure all 4 corners of Aadhaar card are visible",
|
|
94
|
+
"QR code should be clearly visible for verification",
|
|
95
|
+
];
|
|
96
|
+
case "pan":
|
|
97
|
+
return [
|
|
98
|
+
...common,
|
|
99
|
+
"Ensure PAN number is clearly readable",
|
|
100
|
+
"Photo area should not be covered",
|
|
101
|
+
];
|
|
102
|
+
default:
|
|
103
|
+
return common;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ocr/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAgEH,gDA0BC;AAMD,oDAaC;AAMD,4CAGC;AAKD,kCAEC;AAKD,0CAKC;AAKD,0CAwBC;AAvGD;;GAEG;AACH,SAAgB,kBAAkB,CAAC,OAAe;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACnC,IACE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACtC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EACtB,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,eAAe,CAAC;IACrE,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACnE,OAAO,KAAK,CAAC;IACf,IACE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;QAE9B,OAAO,iBAAiB,CAAC;IAC3B,IACE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QACzB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QACtB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAEpB,OAAO,UAAU,CAAC;IACpB,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACjE,OAAO,UAAU,CAAC;IACpB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAgB,oBAAoB,CAAC,IAAY;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,OAAO,aAAa,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACrC,CAAC;IACD,kBAAkB;IAClB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACnD,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5C,OAAO,aAAa,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,GAAW;IACrC,OAAO,yBAAyB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,OAAe;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACnE,qCAAqC;IACrC,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,OAAqB;IACnD,MAAM,MAAM,GAAG;QACb,wCAAwC;QACxC,oCAAoC;QACpC,6CAA6C;KAC9C,CAAC;IAEF,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,eAAe,CAAC;QACrB,KAAK,cAAc;YACjB,OAAO;gBACL,GAAG,MAAM;gBACT,kDAAkD;gBAClD,oDAAoD;aACrD,CAAC;QACJ,KAAK,KAAK;YACR,OAAO;gBACL,GAAG,MAAM;gBACT,uCAAuC;gBACvC,kCAAkC;aACnC,CAAC;QACJ;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rajeev02/edge-ai — ML Pipeline
|
|
3
|
+
* Abstract pipeline for on-device ML: model loading, inference, post-processing
|
|
4
|
+
* Backends: TFLite (Android), CoreML (iOS), ONNX (Web)
|
|
5
|
+
*/
|
|
6
|
+
export type MLBackend = "tflite" | "coreml" | "onnx" | "wasm";
|
|
7
|
+
export type ModelState = "unloaded" | "loading" | "ready" | "inferring" | "error";
|
|
8
|
+
export interface ModelConfig {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
/** Path or URL to the model file */
|
|
12
|
+
modelPath: string;
|
|
13
|
+
/** Which backend to use */
|
|
14
|
+
backend: MLBackend;
|
|
15
|
+
/** Model input dimensions [batch, height, width, channels] */
|
|
16
|
+
inputShape?: number[];
|
|
17
|
+
/** Labels file path (for classification) */
|
|
18
|
+
labelsPath?: string;
|
|
19
|
+
/** Whether to use GPU acceleration */
|
|
20
|
+
useGpu?: boolean;
|
|
21
|
+
/** Number of threads for CPU inference */
|
|
22
|
+
numThreads?: number;
|
|
23
|
+
/** Maximum model file size in bytes (for download check) */
|
|
24
|
+
maxSizeBytes?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface InferenceResult {
|
|
27
|
+
modelId: string;
|
|
28
|
+
/** Time taken for inference in ms */
|
|
29
|
+
inferenceTimeMs: number;
|
|
30
|
+
/** Raw output tensor(s) */
|
|
31
|
+
outputs: Record<string, number[]>;
|
|
32
|
+
/** Post-processed results (model-specific) */
|
|
33
|
+
results: unknown;
|
|
34
|
+
/** Confidence of top result (0-1) */
|
|
35
|
+
topConfidence: number;
|
|
36
|
+
}
|
|
37
|
+
export interface BoundingBox {
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
width: number;
|
|
41
|
+
height: number;
|
|
42
|
+
label: string;
|
|
43
|
+
confidence: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* ML Model Manager — handles loading, caching, and lifecycle of ML models
|
|
47
|
+
*/
|
|
48
|
+
export declare class ModelManager {
|
|
49
|
+
private models;
|
|
50
|
+
private listeners;
|
|
51
|
+
/** Register a model */
|
|
52
|
+
register(config: ModelConfig): void;
|
|
53
|
+
/** Load a model into memory */
|
|
54
|
+
load(modelId: string): Promise<boolean>;
|
|
55
|
+
/** Unload a model from memory */
|
|
56
|
+
unload(modelId: string): boolean;
|
|
57
|
+
/** Get model state */
|
|
58
|
+
getState(modelId: string): ModelState;
|
|
59
|
+
/** Check if a model is ready */
|
|
60
|
+
isReady(modelId: string): boolean;
|
|
61
|
+
/** Get all registered models */
|
|
62
|
+
getAll(): (ModelConfig & {
|
|
63
|
+
state: ModelState;
|
|
64
|
+
})[];
|
|
65
|
+
/** Subscribe to model state changes */
|
|
66
|
+
onStateChange(listener: (modelId: string, state: ModelState) => void): () => void;
|
|
67
|
+
private notify;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pipeline/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAC9D,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,SAAS,GACT,OAAO,GACP,WAAW,GACX,OAAO,CAAC;AAEZ,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,OAAO,EAAE,SAAS,CAAC;IACnB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClC,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA+D;IAC7E,OAAO,CAAC,SAAS,CACL;IAEZ,uBAAuB;IACvB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAInC,+BAA+B;IACzB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW7C,iCAAiC;IACjC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAQhC,sBAAsB;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU;IAIrC,gCAAgC;IAChC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIjC,gCAAgC;IAChC,MAAM,IAAI,CAAC,WAAW,GAAG;QAAE,KAAK,EAAE,UAAU,CAAA;KAAE,CAAC,EAAE;IAIjD,uCAAuC;IACvC,aAAa,CACX,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,KAAK,IAAI,GACrD,MAAM,IAAI;IAKb,OAAO,CAAC,MAAM;CAOf"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @rajeev02/edge-ai — ML Pipeline
|
|
4
|
+
* Abstract pipeline for on-device ML: model loading, inference, post-processing
|
|
5
|
+
* Backends: TFLite (Android), CoreML (iOS), ONNX (Web)
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.ModelManager = void 0;
|
|
9
|
+
/**
|
|
10
|
+
* ML Model Manager — handles loading, caching, and lifecycle of ML models
|
|
11
|
+
*/
|
|
12
|
+
class ModelManager {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.models = new Map();
|
|
15
|
+
this.listeners = new Set();
|
|
16
|
+
}
|
|
17
|
+
/** Register a model */
|
|
18
|
+
register(config) {
|
|
19
|
+
this.models.set(config.id, { ...config, state: "unloaded" });
|
|
20
|
+
}
|
|
21
|
+
/** Load a model into memory */
|
|
22
|
+
async load(modelId) {
|
|
23
|
+
const model = this.models.get(modelId);
|
|
24
|
+
if (!model)
|
|
25
|
+
return false;
|
|
26
|
+
model.state = "loading";
|
|
27
|
+
this.notify(modelId, "loading");
|
|
28
|
+
// Native layer would actually load the model here
|
|
29
|
+
model.state = "ready";
|
|
30
|
+
this.notify(modelId, "ready");
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
/** Unload a model from memory */
|
|
34
|
+
unload(modelId) {
|
|
35
|
+
const model = this.models.get(modelId);
|
|
36
|
+
if (!model)
|
|
37
|
+
return false;
|
|
38
|
+
model.state = "unloaded";
|
|
39
|
+
this.notify(modelId, "unloaded");
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
/** Get model state */
|
|
43
|
+
getState(modelId) {
|
|
44
|
+
return this.models.get(modelId)?.state ?? "unloaded";
|
|
45
|
+
}
|
|
46
|
+
/** Check if a model is ready */
|
|
47
|
+
isReady(modelId) {
|
|
48
|
+
return this.getState(modelId) === "ready";
|
|
49
|
+
}
|
|
50
|
+
/** Get all registered models */
|
|
51
|
+
getAll() {
|
|
52
|
+
return Array.from(this.models.values());
|
|
53
|
+
}
|
|
54
|
+
/** Subscribe to model state changes */
|
|
55
|
+
onStateChange(listener) {
|
|
56
|
+
this.listeners.add(listener);
|
|
57
|
+
return () => this.listeners.delete(listener);
|
|
58
|
+
}
|
|
59
|
+
notify(modelId, state) {
|
|
60
|
+
for (const l of this.listeners) {
|
|
61
|
+
try {
|
|
62
|
+
l(modelId, state);
|
|
63
|
+
}
|
|
64
|
+
catch { }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.ModelManager = ModelManager;
|
|
69
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pipeline/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAkDH;;GAEG;AACH,MAAa,YAAY;IAAzB;QACU,WAAM,GAAqD,IAAI,GAAG,EAAE,CAAC;QACrE,cAAS,GACf,IAAI,GAAG,EAAE,CAAC;IA0Dd,CAAC;IAxDC,uBAAuB;IACvB,QAAQ,CAAC,MAAmB;QAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,+BAA+B;IAC/B,KAAK,CAAC,IAAI,CAAC,OAAe;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAChC,kDAAkD;QAClD,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iCAAiC;IACjC,MAAM,CAAC,OAAe;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,sBAAsB;IACtB,QAAQ,CAAC,OAAe;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,IAAI,UAAU,CAAC;IACvD,CAAC;IAED,gCAAgC;IAChC,OAAO,CAAC,OAAe;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC;IAC5C,CAAC;IAED,gCAAgC;IAChC,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,uCAAuC;IACvC,aAAa,CACX,QAAsD;QAEtD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAEO,MAAM,CAAC,OAAe,EAAE,KAAiB;QAC/C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AA7DD,oCA6DC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rajeev02/edge-ai — Voice Commands
|
|
3
|
+
* On-device wake word detection, speech-to-text, intent parsing for Indian languages
|
|
4
|
+
*/
|
|
5
|
+
export type VoiceState = "idle" | "listening" | "processing" | "speaking";
|
|
6
|
+
export interface VoiceConfig {
|
|
7
|
+
/** Wake word (e.g., "Hey Rajeev", "Ok App") */
|
|
8
|
+
wakeWord?: string;
|
|
9
|
+
/** Language for speech recognition */
|
|
10
|
+
language: string;
|
|
11
|
+
/** Whether to run recognition on-device only */
|
|
12
|
+
offlineOnly?: boolean;
|
|
13
|
+
/** Max listening duration in seconds */
|
|
14
|
+
maxDurationSeconds?: number;
|
|
15
|
+
/** Minimum confidence to accept (0-1) */
|
|
16
|
+
minConfidence?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface SpeechResult {
|
|
19
|
+
/** Recognized text */
|
|
20
|
+
text: string;
|
|
21
|
+
/** Confidence (0-1) */
|
|
22
|
+
confidence: number;
|
|
23
|
+
/** Detected language */
|
|
24
|
+
language: string;
|
|
25
|
+
/** Whether this is a final result or interim */
|
|
26
|
+
isFinal: boolean;
|
|
27
|
+
/** Alternative transcriptions */
|
|
28
|
+
alternatives?: {
|
|
29
|
+
text: string;
|
|
30
|
+
confidence: number;
|
|
31
|
+
}[];
|
|
32
|
+
}
|
|
33
|
+
export interface VoiceIntent {
|
|
34
|
+
/** Parsed intent name (e.g., "navigate", "search", "pay", "call") */
|
|
35
|
+
intent: string;
|
|
36
|
+
/** Confidence of intent classification */
|
|
37
|
+
confidence: number;
|
|
38
|
+
/** Extracted entities */
|
|
39
|
+
entities: Record<string, string>;
|
|
40
|
+
/** Original speech text */
|
|
41
|
+
originalText: string;
|
|
42
|
+
}
|
|
43
|
+
/** Supported Indian languages for voice */
|
|
44
|
+
export declare const SUPPORTED_VOICE_LANGUAGES: Record<string, string>;
|
|
45
|
+
/**
|
|
46
|
+
* Parse simple voice commands into intents
|
|
47
|
+
* This is a rule-based parser for common commands; production would use an NLU model
|
|
48
|
+
*/
|
|
49
|
+
export declare function parseVoiceIntent(text: string, language?: string): VoiceIntent;
|
|
50
|
+
/**
|
|
51
|
+
* Text-to-Speech configuration for Indian languages
|
|
52
|
+
*/
|
|
53
|
+
export declare function getTtsConfig(language: string): {
|
|
54
|
+
rate: number;
|
|
55
|
+
pitch: number;
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/voice/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC;AAE1E,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,wCAAwC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yCAAyC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,OAAO,EAAE,OAAO,CAAC;IACjB,iCAAiC;IACjC,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACvD;AAED,MAAM,WAAW,WAAW;IAC1B,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,2BAA2B;IAC3B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,2CAA2C;AAC3C,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAY5D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAgB,GACzB,WAAW,CAoDb;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAYA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @rajeev02/edge-ai — Voice Commands
|
|
4
|
+
* On-device wake word detection, speech-to-text, intent parsing for Indian languages
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.SUPPORTED_VOICE_LANGUAGES = void 0;
|
|
8
|
+
exports.parseVoiceIntent = parseVoiceIntent;
|
|
9
|
+
exports.getTtsConfig = getTtsConfig;
|
|
10
|
+
/** Supported Indian languages for voice */
|
|
11
|
+
exports.SUPPORTED_VOICE_LANGUAGES = {
|
|
12
|
+
"hi-IN": "Hindi",
|
|
13
|
+
"en-IN": "English (India)",
|
|
14
|
+
"bn-IN": "Bengali",
|
|
15
|
+
"ta-IN": "Tamil",
|
|
16
|
+
"te-IN": "Telugu",
|
|
17
|
+
"mr-IN": "Marathi",
|
|
18
|
+
"gu-IN": "Gujarati",
|
|
19
|
+
"kn-IN": "Kannada",
|
|
20
|
+
"ml-IN": "Malayalam",
|
|
21
|
+
"pa-IN": "Punjabi",
|
|
22
|
+
"or-IN": "Odia",
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Parse simple voice commands into intents
|
|
26
|
+
* This is a rule-based parser for common commands; production would use an NLU model
|
|
27
|
+
*/
|
|
28
|
+
function parseVoiceIntent(text, language = "en-IN") {
|
|
29
|
+
const lower = text.toLowerCase().trim();
|
|
30
|
+
const result = {
|
|
31
|
+
intent: "unknown",
|
|
32
|
+
confidence: 0.5,
|
|
33
|
+
entities: {},
|
|
34
|
+
originalText: text,
|
|
35
|
+
};
|
|
36
|
+
// Navigation intents
|
|
37
|
+
if (/^(go to|open|show|navigate to)\s+(.+)$/i.test(lower)) {
|
|
38
|
+
result.intent = "navigate";
|
|
39
|
+
result.entities.destination = lower.replace(/^(go to|open|show|navigate to)\s+/i, "");
|
|
40
|
+
result.confidence = 0.9;
|
|
41
|
+
}
|
|
42
|
+
// Search
|
|
43
|
+
else if (/^(search|find|look for)\s+(.+)$/i.test(lower)) {
|
|
44
|
+
result.intent = "search";
|
|
45
|
+
result.entities.query = lower.replace(/^(search|find|look for)\s+/i, "");
|
|
46
|
+
result.confidence = 0.9;
|
|
47
|
+
}
|
|
48
|
+
// Payment
|
|
49
|
+
else if (/^(pay|send|transfer)\s+(.+)/i.test(lower)) {
|
|
50
|
+
result.intent = "pay";
|
|
51
|
+
const amountMatch = lower.match(/(\d+)/);
|
|
52
|
+
if (amountMatch)
|
|
53
|
+
result.entities.amount = amountMatch[1];
|
|
54
|
+
const toMatch = lower.match(/to\s+(\w+)/);
|
|
55
|
+
if (toMatch)
|
|
56
|
+
result.entities.recipient = toMatch[1];
|
|
57
|
+
result.confidence = 0.85;
|
|
58
|
+
}
|
|
59
|
+
// Call
|
|
60
|
+
else if (/^(call|phone|dial)\s+(.+)$/i.test(lower)) {
|
|
61
|
+
result.intent = "call";
|
|
62
|
+
result.entities.contact = lower.replace(/^(call|phone|dial)\s+/i, "");
|
|
63
|
+
result.confidence = 0.9;
|
|
64
|
+
}
|
|
65
|
+
// Read aloud
|
|
66
|
+
else if (/^(read|read out|speak)\s+(.+)$/i.test(lower)) {
|
|
67
|
+
result.intent = "read_aloud";
|
|
68
|
+
result.entities.content = lower.replace(/^(read|read out|speak)\s+/i, "");
|
|
69
|
+
result.confidence = 0.85;
|
|
70
|
+
}
|
|
71
|
+
// Help
|
|
72
|
+
else if (/^(help|kya kar sakte|madad)$/i.test(lower)) {
|
|
73
|
+
result.intent = "help";
|
|
74
|
+
result.confidence = 0.95;
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Text-to-Speech configuration for Indian languages
|
|
80
|
+
*/
|
|
81
|
+
function getTtsConfig(language) {
|
|
82
|
+
// Indian languages generally benefit from slightly slower rate
|
|
83
|
+
switch (language) {
|
|
84
|
+
case "hi-IN":
|
|
85
|
+
return { rate: 0.9, pitch: 1.0 };
|
|
86
|
+
case "bn-IN":
|
|
87
|
+
return { rate: 0.85, pitch: 1.0 };
|
|
88
|
+
case "ta-IN":
|
|
89
|
+
return { rate: 0.85, pitch: 1.0 };
|
|
90
|
+
default:
|
|
91
|
+
return { rate: 0.95, pitch: 1.0 };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/voice/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rajeev02/edge-ai",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Edge AI / On-Device ML Toolkit — OCR, face detection, voice commands, document scanner, smart crop",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"author": "Rajeev Kumar Joshi <rajeevjoshi91@gmail.com> (https://rajeev02.github.io)",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"types": "lib/index.d.ts",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"clean": "rm -rf lib",
|
|
12
|
+
"prepublishOnly": "npm run build"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react-native",
|
|
16
|
+
"ai",
|
|
17
|
+
"ml",
|
|
18
|
+
"on-device",
|
|
19
|
+
"inference",
|
|
20
|
+
"nlp"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/Rajeev02/rajeev-sdk",
|
|
25
|
+
"directory": "packages/edge-ai"
|
|
26
|
+
},
|
|
27
|
+
"homepage": "https://github.com/Rajeev02/rajeev-sdk#readme",
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/Rajeev02/rajeev-sdk/issues"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"lib/",
|
|
33
|
+
"src/",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": ">=18.3.0",
|
|
41
|
+
"react-native": ">=0.84.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependenciesMeta": {
|
|
44
|
+
"react-native": {
|
|
45
|
+
"optional": true
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/react": "^19.0.0",
|
|
50
|
+
"typescript": "^5.4.0"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rajeev02/edge-ai
|
|
3
|
+
* Edge AI / On-Device ML Toolkit
|
|
4
|
+
* OCR, face detection, voice commands, document scanning
|
|
5
|
+
*
|
|
6
|
+
* @author Rajeev Kumar Joshi
|
|
7
|
+
* @license MIT
|
|
8
|
+
*/
|
|
9
|
+
export { ModelManager } from "./pipeline";
|
|
10
|
+
export type {
|
|
11
|
+
ModelConfig,
|
|
12
|
+
InferenceResult,
|
|
13
|
+
BoundingBox,
|
|
14
|
+
MLBackend,
|
|
15
|
+
ModelState,
|
|
16
|
+
} from "./pipeline";
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
detectDocumentType,
|
|
20
|
+
extractAadhaarNumber,
|
|
21
|
+
extractPanNumber,
|
|
22
|
+
validatePan,
|
|
23
|
+
validateAadhaar,
|
|
24
|
+
getScanningTips,
|
|
25
|
+
} from "./ocr";
|
|
26
|
+
export type {
|
|
27
|
+
OcrResult,
|
|
28
|
+
OcrBlock,
|
|
29
|
+
AadhaarCardData,
|
|
30
|
+
PanCardData,
|
|
31
|
+
DrivingLicenseData,
|
|
32
|
+
DocumentType,
|
|
33
|
+
} from "./ocr";
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
parseVoiceIntent,
|
|
37
|
+
getTtsConfig,
|
|
38
|
+
SUPPORTED_VOICE_LANGUAGES,
|
|
39
|
+
} from "./voice";
|
|
40
|
+
export type {
|
|
41
|
+
VoiceConfig,
|
|
42
|
+
SpeechResult,
|
|
43
|
+
VoiceIntent,
|
|
44
|
+
VoiceState,
|
|
45
|
+
} from "./voice";
|
package/src/ocr/index.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rajeev02/edge-ai — OCR Module
|
|
3
|
+
* On-device text recognition, document scanning, Indian ID card extraction
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface OcrResult {
|
|
7
|
+
/** Full recognized text */
|
|
8
|
+
text: string;
|
|
9
|
+
/** Individual text blocks with positions */
|
|
10
|
+
blocks: OcrBlock[];
|
|
11
|
+
/** Detected language(s) */
|
|
12
|
+
languages: string[];
|
|
13
|
+
/** Overall confidence (0-1) */
|
|
14
|
+
confidence: number;
|
|
15
|
+
/** Processing time in ms */
|
|
16
|
+
processingTimeMs: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface OcrBlock {
|
|
20
|
+
text: string;
|
|
21
|
+
boundingBox: { x: number; y: number; width: number; height: number };
|
|
22
|
+
confidence: number;
|
|
23
|
+
language?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Extracted data from Indian ID cards */
|
|
27
|
+
export interface AadhaarCardData {
|
|
28
|
+
name?: string;
|
|
29
|
+
aadhaarNumber?: string; // Will be masked: XXXX XXXX 1234
|
|
30
|
+
dateOfBirth?: string;
|
|
31
|
+
gender?: string;
|
|
32
|
+
address?: string;
|
|
33
|
+
pincode?: string;
|
|
34
|
+
photo?: string; // Base64
|
|
35
|
+
confidence: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface PanCardData {
|
|
39
|
+
name?: string;
|
|
40
|
+
panNumber?: string;
|
|
41
|
+
fatherName?: string;
|
|
42
|
+
dateOfBirth?: string;
|
|
43
|
+
confidence: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface DrivingLicenseData {
|
|
47
|
+
name?: string;
|
|
48
|
+
licenseNumber?: string;
|
|
49
|
+
dateOfBirth?: string;
|
|
50
|
+
validity?: string;
|
|
51
|
+
address?: string;
|
|
52
|
+
vehicleClasses?: string[];
|
|
53
|
+
confidence: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type DocumentType =
|
|
57
|
+
| "aadhaar_front"
|
|
58
|
+
| "aadhaar_back"
|
|
59
|
+
| "pan"
|
|
60
|
+
| "driving_license"
|
|
61
|
+
| "voter_id"
|
|
62
|
+
| "passport"
|
|
63
|
+
| "unknown";
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Detect the type of Indian ID document from OCR text
|
|
67
|
+
*/
|
|
68
|
+
export function detectDocumentType(ocrText: string): DocumentType {
|
|
69
|
+
const text = ocrText.toLowerCase();
|
|
70
|
+
if (
|
|
71
|
+
text.includes("aadhaar") ||
|
|
72
|
+
text.includes("unique identification") ||
|
|
73
|
+
text.includes("uidai")
|
|
74
|
+
) {
|
|
75
|
+
return text.includes("address") ? "aadhaar_back" : "aadhaar_front";
|
|
76
|
+
}
|
|
77
|
+
if (text.includes("income tax") || text.includes("permanent account"))
|
|
78
|
+
return "pan";
|
|
79
|
+
if (
|
|
80
|
+
text.includes("driving") ||
|
|
81
|
+
text.includes("licence") ||
|
|
82
|
+
text.includes("motor vehicle")
|
|
83
|
+
)
|
|
84
|
+
return "driving_license";
|
|
85
|
+
if (
|
|
86
|
+
text.includes("election") ||
|
|
87
|
+
text.includes("voter") ||
|
|
88
|
+
text.includes("eci")
|
|
89
|
+
)
|
|
90
|
+
return "voter_id";
|
|
91
|
+
if (text.includes("passport") || text.includes("republic of india"))
|
|
92
|
+
return "passport";
|
|
93
|
+
return "unknown";
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Extract Aadhaar number from OCR text
|
|
98
|
+
* Returns masked format: XXXX XXXX 1234
|
|
99
|
+
*/
|
|
100
|
+
export function extractAadhaarNumber(text: string): string | null {
|
|
101
|
+
const match = text.replace(/\s/g, "").match(/\d{12}/);
|
|
102
|
+
if (match) {
|
|
103
|
+
const num = match[0];
|
|
104
|
+
return `XXXX XXXX ${num.slice(8)}`;
|
|
105
|
+
}
|
|
106
|
+
// Try with spaces
|
|
107
|
+
const spaced = text.match(/\d{4}\s?\d{4}\s?\d{4}/);
|
|
108
|
+
if (spaced) {
|
|
109
|
+
const digits = spaced[0].replace(/\s/g, "");
|
|
110
|
+
return `XXXX XXXX ${digits.slice(8)}`;
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Extract PAN number from OCR text
|
|
117
|
+
* Format: ABCDE1234F
|
|
118
|
+
*/
|
|
119
|
+
export function extractPanNumber(text: string): string | null {
|
|
120
|
+
const match = text.match(/[A-Z]{5}[0-9]{4}[A-Z]/);
|
|
121
|
+
return match ? match[0] : null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Validate PAN number format
|
|
126
|
+
*/
|
|
127
|
+
export function validatePan(pan: string): boolean {
|
|
128
|
+
return /^[A-Z]{5}[0-9]{4}[A-Z]$/.test(pan);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Validate Aadhaar number (Verhoeff checksum)
|
|
133
|
+
*/
|
|
134
|
+
export function validateAadhaar(aadhaar: string): boolean {
|
|
135
|
+
const digits = aadhaar.replace(/\s/g, "");
|
|
136
|
+
if (digits.length !== 12 || !/^\d{12}$/.test(digits)) return false;
|
|
137
|
+
// Basic: first digit can't be 0 or 1
|
|
138
|
+
return digits[0] !== "0" && digits[0] !== "1";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Suggested document scanning tips for better OCR
|
|
143
|
+
*/
|
|
144
|
+
export function getScanningTips(docType: DocumentType): string[] {
|
|
145
|
+
const common = [
|
|
146
|
+
"Place document on a flat, dark surface",
|
|
147
|
+
"Ensure good lighting without glare",
|
|
148
|
+
"Keep camera steady and parallel to document",
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
switch (docType) {
|
|
152
|
+
case "aadhaar_front":
|
|
153
|
+
case "aadhaar_back":
|
|
154
|
+
return [
|
|
155
|
+
...common,
|
|
156
|
+
"Ensure all 4 corners of Aadhaar card are visible",
|
|
157
|
+
"QR code should be clearly visible for verification",
|
|
158
|
+
];
|
|
159
|
+
case "pan":
|
|
160
|
+
return [
|
|
161
|
+
...common,
|
|
162
|
+
"Ensure PAN number is clearly readable",
|
|
163
|
+
"Photo area should not be covered",
|
|
164
|
+
];
|
|
165
|
+
default:
|
|
166
|
+
return common;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rajeev02/edge-ai — ML Pipeline
|
|
3
|
+
* Abstract pipeline for on-device ML: model loading, inference, post-processing
|
|
4
|
+
* Backends: TFLite (Android), CoreML (iOS), ONNX (Web)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type MLBackend = "tflite" | "coreml" | "onnx" | "wasm";
|
|
8
|
+
export type ModelState =
|
|
9
|
+
| "unloaded"
|
|
10
|
+
| "loading"
|
|
11
|
+
| "ready"
|
|
12
|
+
| "inferring"
|
|
13
|
+
| "error";
|
|
14
|
+
|
|
15
|
+
export interface ModelConfig {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
/** Path or URL to the model file */
|
|
19
|
+
modelPath: string;
|
|
20
|
+
/** Which backend to use */
|
|
21
|
+
backend: MLBackend;
|
|
22
|
+
/** Model input dimensions [batch, height, width, channels] */
|
|
23
|
+
inputShape?: number[];
|
|
24
|
+
/** Labels file path (for classification) */
|
|
25
|
+
labelsPath?: string;
|
|
26
|
+
/** Whether to use GPU acceleration */
|
|
27
|
+
useGpu?: boolean;
|
|
28
|
+
/** Number of threads for CPU inference */
|
|
29
|
+
numThreads?: number;
|
|
30
|
+
/** Maximum model file size in bytes (for download check) */
|
|
31
|
+
maxSizeBytes?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface InferenceResult {
|
|
35
|
+
modelId: string;
|
|
36
|
+
/** Time taken for inference in ms */
|
|
37
|
+
inferenceTimeMs: number;
|
|
38
|
+
/** Raw output tensor(s) */
|
|
39
|
+
outputs: Record<string, number[]>;
|
|
40
|
+
/** Post-processed results (model-specific) */
|
|
41
|
+
results: unknown;
|
|
42
|
+
/** Confidence of top result (0-1) */
|
|
43
|
+
topConfidence: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface BoundingBox {
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
width: number;
|
|
50
|
+
height: number;
|
|
51
|
+
label: string;
|
|
52
|
+
confidence: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* ML Model Manager — handles loading, caching, and lifecycle of ML models
|
|
57
|
+
*/
|
|
58
|
+
export class ModelManager {
|
|
59
|
+
private models: Map<string, ModelConfig & { state: ModelState }> = new Map();
|
|
60
|
+
private listeners: Set<(modelId: string, state: ModelState) => void> =
|
|
61
|
+
new Set();
|
|
62
|
+
|
|
63
|
+
/** Register a model */
|
|
64
|
+
register(config: ModelConfig): void {
|
|
65
|
+
this.models.set(config.id, { ...config, state: "unloaded" });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Load a model into memory */
|
|
69
|
+
async load(modelId: string): Promise<boolean> {
|
|
70
|
+
const model = this.models.get(modelId);
|
|
71
|
+
if (!model) return false;
|
|
72
|
+
model.state = "loading";
|
|
73
|
+
this.notify(modelId, "loading");
|
|
74
|
+
// Native layer would actually load the model here
|
|
75
|
+
model.state = "ready";
|
|
76
|
+
this.notify(modelId, "ready");
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Unload a model from memory */
|
|
81
|
+
unload(modelId: string): boolean {
|
|
82
|
+
const model = this.models.get(modelId);
|
|
83
|
+
if (!model) return false;
|
|
84
|
+
model.state = "unloaded";
|
|
85
|
+
this.notify(modelId, "unloaded");
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Get model state */
|
|
90
|
+
getState(modelId: string): ModelState {
|
|
91
|
+
return this.models.get(modelId)?.state ?? "unloaded";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Check if a model is ready */
|
|
95
|
+
isReady(modelId: string): boolean {
|
|
96
|
+
return this.getState(modelId) === "ready";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Get all registered models */
|
|
100
|
+
getAll(): (ModelConfig & { state: ModelState })[] {
|
|
101
|
+
return Array.from(this.models.values());
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Subscribe to model state changes */
|
|
105
|
+
onStateChange(
|
|
106
|
+
listener: (modelId: string, state: ModelState) => void,
|
|
107
|
+
): () => void {
|
|
108
|
+
this.listeners.add(listener);
|
|
109
|
+
return () => this.listeners.delete(listener);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private notify(modelId: string, state: ModelState): void {
|
|
113
|
+
for (const l of this.listeners) {
|
|
114
|
+
try {
|
|
115
|
+
l(modelId, state);
|
|
116
|
+
} catch {}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rajeev02/edge-ai — Voice Commands
|
|
3
|
+
* On-device wake word detection, speech-to-text, intent parsing for Indian languages
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type VoiceState = "idle" | "listening" | "processing" | "speaking";
|
|
7
|
+
|
|
8
|
+
export interface VoiceConfig {
|
|
9
|
+
/** Wake word (e.g., "Hey Rajeev", "Ok App") */
|
|
10
|
+
wakeWord?: string;
|
|
11
|
+
/** Language for speech recognition */
|
|
12
|
+
language: string;
|
|
13
|
+
/** Whether to run recognition on-device only */
|
|
14
|
+
offlineOnly?: boolean;
|
|
15
|
+
/** Max listening duration in seconds */
|
|
16
|
+
maxDurationSeconds?: number;
|
|
17
|
+
/** Minimum confidence to accept (0-1) */
|
|
18
|
+
minConfidence?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface SpeechResult {
|
|
22
|
+
/** Recognized text */
|
|
23
|
+
text: string;
|
|
24
|
+
/** Confidence (0-1) */
|
|
25
|
+
confidence: number;
|
|
26
|
+
/** Detected language */
|
|
27
|
+
language: string;
|
|
28
|
+
/** Whether this is a final result or interim */
|
|
29
|
+
isFinal: boolean;
|
|
30
|
+
/** Alternative transcriptions */
|
|
31
|
+
alternatives?: { text: string; confidence: number }[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface VoiceIntent {
|
|
35
|
+
/** Parsed intent name (e.g., "navigate", "search", "pay", "call") */
|
|
36
|
+
intent: string;
|
|
37
|
+
/** Confidence of intent classification */
|
|
38
|
+
confidence: number;
|
|
39
|
+
/** Extracted entities */
|
|
40
|
+
entities: Record<string, string>;
|
|
41
|
+
/** Original speech text */
|
|
42
|
+
originalText: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Supported Indian languages for voice */
|
|
46
|
+
export const SUPPORTED_VOICE_LANGUAGES: Record<string, string> = {
|
|
47
|
+
"hi-IN": "Hindi",
|
|
48
|
+
"en-IN": "English (India)",
|
|
49
|
+
"bn-IN": "Bengali",
|
|
50
|
+
"ta-IN": "Tamil",
|
|
51
|
+
"te-IN": "Telugu",
|
|
52
|
+
"mr-IN": "Marathi",
|
|
53
|
+
"gu-IN": "Gujarati",
|
|
54
|
+
"kn-IN": "Kannada",
|
|
55
|
+
"ml-IN": "Malayalam",
|
|
56
|
+
"pa-IN": "Punjabi",
|
|
57
|
+
"or-IN": "Odia",
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Parse simple voice commands into intents
|
|
62
|
+
* This is a rule-based parser for common commands; production would use an NLU model
|
|
63
|
+
*/
|
|
64
|
+
export function parseVoiceIntent(
|
|
65
|
+
text: string,
|
|
66
|
+
language: string = "en-IN",
|
|
67
|
+
): VoiceIntent {
|
|
68
|
+
const lower = text.toLowerCase().trim();
|
|
69
|
+
const result: VoiceIntent = {
|
|
70
|
+
intent: "unknown",
|
|
71
|
+
confidence: 0.5,
|
|
72
|
+
entities: {},
|
|
73
|
+
originalText: text,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Navigation intents
|
|
77
|
+
if (/^(go to|open|show|navigate to)\s+(.+)$/i.test(lower)) {
|
|
78
|
+
result.intent = "navigate";
|
|
79
|
+
result.entities.destination = lower.replace(
|
|
80
|
+
/^(go to|open|show|navigate to)\s+/i,
|
|
81
|
+
"",
|
|
82
|
+
);
|
|
83
|
+
result.confidence = 0.9;
|
|
84
|
+
}
|
|
85
|
+
// Search
|
|
86
|
+
else if (/^(search|find|look for)\s+(.+)$/i.test(lower)) {
|
|
87
|
+
result.intent = "search";
|
|
88
|
+
result.entities.query = lower.replace(/^(search|find|look for)\s+/i, "");
|
|
89
|
+
result.confidence = 0.9;
|
|
90
|
+
}
|
|
91
|
+
// Payment
|
|
92
|
+
else if (/^(pay|send|transfer)\s+(.+)/i.test(lower)) {
|
|
93
|
+
result.intent = "pay";
|
|
94
|
+
const amountMatch = lower.match(/(\d+)/);
|
|
95
|
+
if (amountMatch) result.entities.amount = amountMatch[1];
|
|
96
|
+
const toMatch = lower.match(/to\s+(\w+)/);
|
|
97
|
+
if (toMatch) result.entities.recipient = toMatch[1];
|
|
98
|
+
result.confidence = 0.85;
|
|
99
|
+
}
|
|
100
|
+
// Call
|
|
101
|
+
else if (/^(call|phone|dial)\s+(.+)$/i.test(lower)) {
|
|
102
|
+
result.intent = "call";
|
|
103
|
+
result.entities.contact = lower.replace(/^(call|phone|dial)\s+/i, "");
|
|
104
|
+
result.confidence = 0.9;
|
|
105
|
+
}
|
|
106
|
+
// Read aloud
|
|
107
|
+
else if (/^(read|read out|speak)\s+(.+)$/i.test(lower)) {
|
|
108
|
+
result.intent = "read_aloud";
|
|
109
|
+
result.entities.content = lower.replace(/^(read|read out|speak)\s+/i, "");
|
|
110
|
+
result.confidence = 0.85;
|
|
111
|
+
}
|
|
112
|
+
// Help
|
|
113
|
+
else if (/^(help|kya kar sakte|madad)$/i.test(lower)) {
|
|
114
|
+
result.intent = "help";
|
|
115
|
+
result.confidence = 0.95;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Text-to-Speech configuration for Indian languages
|
|
123
|
+
*/
|
|
124
|
+
export function getTtsConfig(language: string): {
|
|
125
|
+
rate: number;
|
|
126
|
+
pitch: number;
|
|
127
|
+
} {
|
|
128
|
+
// Indian languages generally benefit from slightly slower rate
|
|
129
|
+
switch (language) {
|
|
130
|
+
case "hi-IN":
|
|
131
|
+
return { rate: 0.9, pitch: 1.0 };
|
|
132
|
+
case "bn-IN":
|
|
133
|
+
return { rate: 0.85, pitch: 1.0 };
|
|
134
|
+
case "ta-IN":
|
|
135
|
+
return { rate: 0.85, pitch: 1.0 };
|
|
136
|
+
default:
|
|
137
|
+
return { rate: 0.95, pitch: 1.0 };
|
|
138
|
+
}
|
|
139
|
+
}
|