**feat(tests): add tests for TextEncoder, TensorFlow.js, and fallback mechanisms**
- Introduced `test-fallback-function.js` and `test-fallback-simple.js` to validate `executeInThread` fallback functionality with both named and anonymous compute-intensive functions. - Added `test-tensorflow-textencoder.js` for TensorFlow.js and TextEncoder tests in a Node.js environment. - Created `test-tensorflow-textencoder.html` for browser-based TensorFlow.js and TextEncoder tests. - Implemented cross-environment test support in `cli-package/src/test-tensorflow-textencoder.ts` for CLI functionality. - Enhanced `src/utils/embedding.ts`, `textEncoding.ts`, and `brainy-wrapper.js` to include updated global `TextEncoder` and `TextDecoder` utilities for compatibility and worker improvements. - Standardized and expanded utility methods in `PlatformNode` for broader support, including `isFloat32Array` and `isTypedArray` checks. - Updated Node.js requirement to `>= 24.4.0` across documentation and configuration files for compatibility improvements. This update introduces comprehensive testing for fallback mechanisms, TensorFlow.js, and TextEncoder across multiple environments, ensuring robustness and compatibility.
This commit is contained in:
parent
04a33b9ae8
commit
5f267b14ed
30 changed files with 1799 additions and 1583 deletions
|
|
@ -5,13 +5,8 @@
|
|||
* A command-line interface for interacting with the Brainy vector database
|
||||
*/
|
||||
|
||||
// Import the unified text encoding utilities
|
||||
// This needs to be done before importing @soulcraft/brainy
|
||||
import { applyTensorFlowPatch } from './utils/textEncoding.js'
|
||||
|
||||
// Apply the TensorFlow.js platform patch if needed
|
||||
// Log environment information
|
||||
console.log('Brainy running in Node.js environment')
|
||||
applyTensorFlowPatch()
|
||||
|
||||
import {
|
||||
BrainyData,
|
||||
|
|
@ -1360,6 +1355,21 @@ augmentCommand
|
|||
// Add the augment command to the program
|
||||
program.addCommand(augmentCommand)
|
||||
|
||||
// Add a top-level test-tensorflow-textencoder command
|
||||
program
|
||||
.command('test-tensorflow-textencoder')
|
||||
.description('Test TensorFlow.js and TextEncoder functionality')
|
||||
.action(async () => {
|
||||
try {
|
||||
// Import the test function from the test file
|
||||
const { runTest } = await import('./test-tensorflow-textencoder.js')
|
||||
await runTest()
|
||||
} catch (error) {
|
||||
console.error('Error:', (error as Error).message)
|
||||
process.exit(1)
|
||||
}
|
||||
})
|
||||
|
||||
// Add a top-level test-pipeline command that redirects to augment test-pipeline
|
||||
program
|
||||
.command('test-pipeline')
|
||||
|
|
|
|||
102
cli-package/src/test-tensorflow-textencoder.ts
Normal file
102
cli-package/src/test-tensorflow-textencoder.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* CLI Test for TensorFlow.js and TextEncoder
|
||||
*
|
||||
* This script tests TensorFlow.js and TextEncoder functionality in the CLI environment.
|
||||
*/
|
||||
|
||||
import {
|
||||
getTextEncoder,
|
||||
getTextDecoder
|
||||
} from '@soulcraft/brainy/dist/utils/textEncoding.js'
|
||||
import * as tf from '@tensorflow/tfjs'
|
||||
import '@tensorflow/tfjs-backend-cpu'
|
||||
|
||||
export async function testTensorFlowAndTextEncoder(): Promise<boolean> {
|
||||
console.log('Testing TensorFlow.js and TextEncoder in CLI environment...')
|
||||
|
||||
try {
|
||||
// TensorFlow patch is automatically applied by the main package
|
||||
console.log('Using TensorFlow with automatic patching')
|
||||
|
||||
// Test TextEncoder
|
||||
console.log('\n--- Testing TextEncoder ---')
|
||||
const encoder = getTextEncoder()
|
||||
const decoder = getTextDecoder()
|
||||
|
||||
const testString = 'Hello, world! 👋'
|
||||
console.log(`Original string: "${testString}"`)
|
||||
|
||||
const encoded = encoder.encode(testString)
|
||||
console.log(`Encoded: [${encoded}]`)
|
||||
|
||||
const decoded = decoder.decode(encoded)
|
||||
console.log(`Decoded: "${decoded}"`)
|
||||
|
||||
if (testString === decoded) {
|
||||
console.log('✅ TextEncoder/TextDecoder test passed!')
|
||||
} else {
|
||||
console.error('❌ TextEncoder/TextDecoder test failed!')
|
||||
return false
|
||||
}
|
||||
|
||||
// Test TensorFlow.js
|
||||
console.log('\n--- Testing TensorFlow.js ---')
|
||||
|
||||
// Create a simple tensor
|
||||
const tensor = tf.tensor2d([
|
||||
[1, 2],
|
||||
[3, 4]
|
||||
])
|
||||
console.log('Created tensor:')
|
||||
tensor.print()
|
||||
|
||||
// Perform a simple operation
|
||||
const result = tensor.add(tf.scalar(1))
|
||||
console.log('Result of adding 1:')
|
||||
result.print()
|
||||
|
||||
// Check the values
|
||||
const values = await result.array()
|
||||
const expected = [
|
||||
[2, 3],
|
||||
[4, 5]
|
||||
]
|
||||
|
||||
console.log('Result values:', values)
|
||||
console.log('Expected values:', expected)
|
||||
|
||||
// Compare values
|
||||
const match = JSON.stringify(values) === JSON.stringify(expected)
|
||||
if (match) {
|
||||
console.log('✅ TensorFlow.js test passed!')
|
||||
} else {
|
||||
console.error('❌ TensorFlow.js test failed!')
|
||||
return false
|
||||
}
|
||||
|
||||
console.log('\nAll tests passed successfully!')
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error('Error during test:', error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// This function can be called from the CLI
|
||||
export async function runTest(): Promise<void> {
|
||||
const success = await testTensorFlowAndTextEncoder()
|
||||
if (success) {
|
||||
console.log(
|
||||
'TensorFlow.js and TextEncoder verification completed successfully!'
|
||||
)
|
||||
process.exit(0)
|
||||
} else {
|
||||
console.error('TensorFlow.js and TextEncoder verification failed!')
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// If this file is run directly
|
||||
if (typeof require !== 'undefined' && require.main === module) {
|
||||
runTest()
|
||||
}
|
||||
|
|
@ -2,13 +2,13 @@
|
|||
* Unified Text Encoding Utilities for CLI
|
||||
*
|
||||
* This module provides a consistent way to handle text encoding/decoding across all environments
|
||||
* without relying on TextEncoder/TextDecoder polyfills or patches.
|
||||
* using the native TextEncoder/TextDecoder APIs.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Apply the TensorFlow.js platform patch if needed
|
||||
* This function patches the global object to provide a PlatformNode class
|
||||
* that uses our text encoding utilities instead of relying on TextEncoder/TextDecoder
|
||||
* that uses native TextEncoder/TextDecoder
|
||||
*/
|
||||
export function applyTensorFlowPatch(): void {
|
||||
// Only apply in Node.js environment
|
||||
|
|
@ -22,20 +22,32 @@ export function applyTensorFlowPatch(): void {
|
|||
// Define a custom PlatformNode class
|
||||
class PlatformNode {
|
||||
util: any
|
||||
textEncoder: any
|
||||
textDecoder: any
|
||||
textEncoder: TextEncoder
|
||||
textDecoder: TextDecoder
|
||||
|
||||
constructor() {
|
||||
// Create a util object with necessary methods and constructors
|
||||
this.util = {
|
||||
// Add isFloat32Array and isTypedArray directly to util
|
||||
isFloat32Array: (arr: any) => {
|
||||
return !!(
|
||||
arr instanceof Float32Array ||
|
||||
(arr &&
|
||||
Object.prototype.toString.call(arr) ===
|
||||
'[object Float32Array]')
|
||||
)
|
||||
},
|
||||
isTypedArray: (arr: any) => {
|
||||
return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView))
|
||||
},
|
||||
// Use native TextEncoder and TextDecoder
|
||||
TextEncoder: TextEncoder,
|
||||
TextDecoder: TextDecoder
|
||||
}
|
||||
|
||||
// Initialize using the constructors from util
|
||||
this.textEncoder = new this.util.TextEncoder()
|
||||
this.textDecoder = new this.util.TextDecoder()
|
||||
// Initialize using native constructors
|
||||
this.textEncoder = new TextEncoder()
|
||||
this.textDecoder = new TextDecoder()
|
||||
}
|
||||
|
||||
// Define isFloat32Array directly on the instance
|
||||
|
|
@ -43,8 +55,7 @@ export function applyTensorFlowPatch(): void {
|
|||
return !!(
|
||||
arr instanceof Float32Array ||
|
||||
(arr &&
|
||||
Object.prototype.toString.call(arr) ===
|
||||
'[object Float32Array]')
|
||||
Object.prototype.toString.call(arr) === '[object Float32Array]')
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -59,6 +70,30 @@ export function applyTensorFlowPatch(): void {
|
|||
|
||||
// Also create an instance and assign it to global.platformNode (lowercase p)
|
||||
;(global as any).platformNode = new PlatformNode()
|
||||
|
||||
// Ensure global.util exists and has the necessary methods
|
||||
// This is needed because TensorFlow.js might look for these methods in global.util
|
||||
if (!(global as any).util) {
|
||||
;(global as any).util = {}
|
||||
}
|
||||
|
||||
// Add isFloat32Array method if it doesn't exist
|
||||
if (!(global as any).util.isFloat32Array) {
|
||||
;(global as any).util.isFloat32Array = (arr: any) => {
|
||||
return !!(
|
||||
arr instanceof Float32Array ||
|
||||
(arr &&
|
||||
Object.prototype.toString.call(arr) === '[object Float32Array]')
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Add isTypedArray method if it doesn't exist
|
||||
if (!(global as any).util.isTypedArray) {
|
||||
;(global as any).util.isTypedArray = (arr: any) => {
|
||||
return !!(ArrayBuffer.isView(arr) && !(arr instanceof DataView))
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to apply TensorFlow.js platform patch:', error)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue