8.0 RC cleanup toward "one place per thing, zero-config, no deprecation":
- Remove the `brain.neural()` clustering namespace (ImprovedNeuralAPI + the dead
legacy NeuralAPI + the neural CLI + neural-only types). Similarity is `find({vector})`
/ `similar({to})`; attribute grouping is the aggregation `GROUP BY` engine. The separate
entity-extraction / smart-import feature (NeuralImport, NeuralEntityExtractor, SmartExtractor,
NaturalLanguageProcessor, `brain.extract()`/`brain.nlp()`) is kept.
- Remove `Db.search()`; `find()` is the one query verb (accepts a bare string or FindParams).
Fix the bundled MCP client, which called a non-existent `brain.search(query, limit)` →
now `find({ query, limit })`.
- Storage config: collapse to one canonical top-level `path` key. The pre-8.0 aliases
(`rootDirectory`, `options.*`, `fileSystemStorage.*`) are removed and now THROW with the
exact rename instead of silently defaulting to `./brainy-data` on upgrade. A single resolver
feeds createStorage, the 7.x→8.0 migration probe, and the plugin-factory handoff, so a native
storage provider resolves the identical root (no split-brain).
- Fix `similar({ threshold })`: the min-similarity filter was silently dropped; it is now
applied as a post-filter on `result.score` (the documented way to bound semantic results).
- Fix `vfs.rename()` on a directory: child path updates spread the entity vector into `update()`
and failed dimension validation; they are metadata-only updates now.
- Fix `vfs.move()`: copy+delete orphaned the content-addressed content blob (the destination
shared the source hash, then unlink removed it). `move()` now delegates to `rename()` — an
in-place path change that preserves the blob and the entity id, for files and directories.
- Fix streaming import: the bulk fast path never flushed mid-import nor signalled queryability.
Entity writes are now chunked by a progressive flush interval (100 → 1000 → 5000); each chunk
flushes and emits `progress.queryable`, so imported data is queryable during the import.
- Sweep all docs, comments, and JSDoc for the removed/changed APIs.
Integration suite: 49 files / 588 passed / 0 failed. Unit: 80 files / 1456 passed, no type errors.
134 lines
No EOL
4.2 KiB
JavaScript
134 lines
No EOL
4.2 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* Quick Brainy 3.0 Performance Test
|
||
*/
|
||
|
||
import { Brainy } from '../dist/brainy.js'
|
||
import { NounType, VerbType } from '../dist/types/graphTypes.js'
|
||
|
||
async function testV3() {
|
||
console.log('🚀 Brainy v3 Quick Performance Test')
|
||
console.log('═'.repeat(50))
|
||
|
||
const brain = new Brainy({
|
||
storage: { type: 'memory' },
|
||
warmup: false,
|
||
embedder: async () => new Array(384).fill(0).map(() => Math.random())
|
||
})
|
||
|
||
console.log('Initializing...')
|
||
await brain.init()
|
||
|
||
// Test 1: Add operations
|
||
console.log('\n📝 Testing Add Operations...')
|
||
const start1 = Date.now()
|
||
const ids = []
|
||
for (let i = 0; i < 100; i++) {
|
||
const id = await brain.add({
|
||
vector: new Array(384).fill(0).map(() => Math.random()),
|
||
type: NounType.Document,
|
||
metadata: { index: i, title: `Doc ${i}` }
|
||
})
|
||
ids.push(id)
|
||
}
|
||
const addTime = Date.now() - start1
|
||
console.log(`✅ Add 100 items: ${addTime}ms (${Math.round(100 / (addTime / 1000))} ops/sec)`)
|
||
|
||
// Test 2: Get operations
|
||
console.log('\n🔍 Testing Get Operations...')
|
||
const start2 = Date.now()
|
||
for (let i = 0; i < 10; i++) {
|
||
const entity = await brain.get(ids[i])
|
||
if (!entity) throw new Error('Entity not found')
|
||
}
|
||
const getTime = Date.now() - start2
|
||
console.log(`✅ Get 10 items: ${getTime}ms (${Math.round(10 / (getTime / 1000))} ops/sec)`)
|
||
|
||
// Test 3: Search operations
|
||
console.log('\n🔎 Testing Search Operations...')
|
||
const start3 = Date.now()
|
||
const results = await brain.find({
|
||
vector: new Array(384).fill(0).map(() => Math.random()),
|
||
limit: 10
|
||
})
|
||
const searchTime = Date.now() - start3
|
||
console.log(`✅ Vector search: ${searchTime}ms, found ${results.length} results`)
|
||
|
||
// Test 4: Metadata filter
|
||
console.log('\n🏷️ Testing Metadata Filters...')
|
||
const start4 = Date.now()
|
||
const filtered = await brain.find({
|
||
where: { 'index': { $gt: 50 } },
|
||
limit: 10
|
||
})
|
||
const filterTime = Date.now() - start4
|
||
console.log(`✅ Metadata filter: ${filterTime}ms, found ${filtered.length} results`)
|
||
|
||
// Test 5: Relationships
|
||
console.log('\n🔗 Testing Relationships...')
|
||
const start5 = Date.now()
|
||
for (let i = 0; i < 10; i++) {
|
||
await brain.relate({
|
||
from: ids[i],
|
||
type: VerbType.References,
|
||
to: ids[i + 1],
|
||
weight: 0.8
|
||
})
|
||
}
|
||
const relateTime = Date.now() - start5
|
||
console.log(`✅ Create 10 relationships: ${relateTime}ms (${Math.round(10 / (relateTime / 1000))} ops/sec)`)
|
||
|
||
// Test 6: Batch operations
|
||
console.log('\n📦 Testing Batch Operations...')
|
||
const start6 = Date.now()
|
||
const batchData = Array(50).fill(0).map((_, i) => ({
|
||
vector: new Array(384).fill(0).map(() => Math.random()),
|
||
type: NounType.Document,
|
||
metadata: { batch: true, index: i }
|
||
}))
|
||
const batchResult = await brain.addMany({ items: batchData })
|
||
const batchTime = Date.now() - start6
|
||
console.log(`✅ Batch add 50 items: ${batchTime}ms (${Math.round(50 / (batchTime / 1000))} ops/sec)`)
|
||
console.log(` Success: ${batchResult.successful.length}, Failed: ${batchResult.failed.length}`)
|
||
|
||
// Test 8: Streaming Pipeline
|
||
console.log('\n🌊 Testing Streaming Pipeline...')
|
||
const { Pipeline } = await import('../dist/streaming/pipeline.js')
|
||
const pipeline = new Pipeline(brain)
|
||
|
||
let streamCount = 0
|
||
const start8 = Date.now()
|
||
|
||
await pipeline
|
||
.source(async function* () {
|
||
for (let i = 0; i < 20; i++) {
|
||
yield { content: `Stream item ${i}`, index: i }
|
||
}
|
||
})
|
||
.map(item => ({
|
||
...item,
|
||
processed: true,
|
||
timestamp: Date.now()
|
||
}))
|
||
.filter(item => item.index % 2 === 0)
|
||
.sink(() => { streamCount++ })
|
||
.run()
|
||
|
||
const streamTime = Date.now() - start8
|
||
console.log(`✅ Streamed ${streamCount} items: ${streamTime}ms`)
|
||
|
||
await brain.close()
|
||
|
||
console.log('\n✨ Summary')
|
||
console.log('═'.repeat(50))
|
||
console.log('All v3 features working correctly!')
|
||
console.log('Key advantages over v2:')
|
||
console.log('- Consistent object-based API')
|
||
console.log('- Built-in batch operations')
|
||
console.log('- Neural clustering API')
|
||
console.log('- Streaming pipeline support')
|
||
console.log('- Better TypeScript support')
|
||
}
|
||
|
||
testV3().catch(console.error) |