Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 69 additions & 0 deletions packages/jeparag/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# @magek/jeparag

> Native **Joint Embedding Predictive Architecture (JEPA)** + **Okapi BM25** Hybrid Retrieval Engine for Magek Ambient Agents.

---

## 🧠 Overview

`@magek/jeparag` brings advanced hybrid RAG capabilities natively into the **Magek** event-driven framework. It combines dense vector semantic representations (JEPA) with sparse keyword matching (Okapi BM25) using **Reciprocal Rank Fusion (RRF)**.

Designed for high-precision, zero-recall-loss applications such as legal auditing, compliance monitoring, and technical log diagnostics.

---

## ⚡ Key Features

- **DocumentLoader & Sliding Window Chunker**: Preserves semantic continuity with configurable chunk sizes (e.g., 256 words, 50 overlap).
- **JEPA Embedder**: Multi-provider embedding engine (Google Gemini, OpenAI, Hash local fallback).
- **BM25 Sparse Keyword Index**: Native Okapi BM25 implementation in TypeScript.
- **Reciprocal Rank Fusion (RRF)**: Merges dense vector cosine similarity ranks with BM25 ranks ($k=60$).
- **Magek Event Sourcing Integration**: Emits immutable events (`DocumentIngestedEvent`, `ChunkEmbeddedEvent`, `JeparagQueryProcessedEvent`).
- **JeparagAmbientAgent**: Proactive background worker reacting to event streams and executing contextual RAG generation.

---

## 🚀 Usage Example

```typescript
import {
DocumentIngestedEvent,
JeparagAmbientAgent,
JeparagHybridSearchReadModel
} from '@magek/jeparag'

// 1. Instantiate Magek Ambient Agent
const agent = new JeparagAmbientAgent('hash')

// 2. Ingest document event
const ingestEvent = new DocumentIngestedEvent(
'doc-101',
'HIPAA Compliance Policy',
'Section 1: Sign-in sheets that reveal patient names are prohibited...'
)

// 3. Process ingestion and populate ReadModel
await agent.onDocumentIngested(ingestEvent)

// 4. Execute hybrid query
const queryResult = await agent.processQuery('query-1', 'sign-in sheet violations', 5)

console.log(queryResult.answer)
```

---

## 🧪 Testing

Run unit tests:

```bash
cd packages/jeparag
rushx test
```

---

## 📜 License

Licensed under Apache-2.0.
72 changes: 72 additions & 0 deletions packages/jeparag/examples/hipaa-audit-demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* Full Executable Demonstration of @magek/jeparag
*
* Demonstrates HIPAA Privacy Audit using Magek Ambient Agents,
* BM25 Sparse Search, JEPA Dense Vector Search, and Reciprocal Rank Fusion (RRF).
*/

import {
DocumentIngestedEvent,
JeparagAmbientAgent,
JeparagHybridSearchReadModel,
} from '../src/index'

async function runDemo(): Promise<void> {
console.log('===============================================================')
console.log('🤖 @magek/jeparag: HIPAA Privacy Compliance Audit Demo')
console.log('===============================================================\n')

// 1. Initialize Magek Ambient Agent
const agent = new JeparagAmbientAgent('hash')
JeparagHybridSearchReadModel.clear()

// 2. Sample HIPAA Regulations Document Corpus (14 Violations)
const hipaaDocumentText = `
HIPAA Privacy and Security Standards - Common Administrative and Technical Violations:

1. Sign-in sheets that reveal individuals who have received prescriptions at your pharmacy.
2. Unsecured transfer of information from a PDA to another database using a wireless connection.
3. A PDA device that does not use a locking system on patient-related information.
4. Discussion about a particular patient in a public area regardless of whether the patient's name is mentioned.
5. Computer monitors that can be seen by unauthorized personnel.
6. Use of generic user names and passwords across clinical workstations.
7. Computer terminals that cannot be locked when not in use.
8. Access to computer records that are not automatically terminated after a period of idle time.
9. Printer or fax outputs containing sensitive patient records that can be seen by unauthorized personnel.
10. Lack of an audit trail on who has had access to patient information.
11. Printed material with patient-related information that is not shredded or destroyed prior to disposal.
12. Group e-mail to patients on upcoming events where recipients can see other recipients' addresses.
13. Individual utilization of patient information or addresses sent to pharmaceutical or marketing firms.
14. Discussion of work events that includes specific information about a patient with unauthorized individuals.
`

console.log('📄 Step 1: Ingesting HIPAA Document into Magek Event Stream...')
const ingestEvent = new DocumentIngestedEvent(
'hipaa-doc-2026',
'HIPAA Compliance Audit Manual',
hipaaDocumentText
)

const embeddedEvents = await agent.onDocumentIngested(ingestEvent)
console.log(`✅ Document successfully chunked and projected into ReadModel (${embeddedEvents.length} chunks generated).\n`)

// 3. Process RAG Query via JeparagAmbientAgent
const searchQuery = 'give me several examples of HIPAA privacy violations'
console.log(`🔍 Step 2: Agent executing Hybrid RRF Query: "${searchQuery}"...`)

const queryEvent = await agent.processQuery('q-audit-101', searchQuery, 5)

console.log('\n📊 Step 3: RAG Retrieval Results & Synthesis:')
console.log('---------------------------------------------------------------')
console.log(`Query ID: ${queryEvent.queryId}`)
console.log(`Retrieved Chunks: ${queryEvent.retrievedChunkIds.join(', ')}`)
console.log('\n--- Generated Response ---')
console.log(queryEvent.answer)
console.log('---------------------------------------------------------------\n')
console.log('✨ Demo Completed Successfully!')
}

runDemo().catch((err) => {
console.error('❌ Demo execution failed:', err)
process.exit(1)
})
69 changes: 69 additions & 0 deletions packages/jeparag/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"name": "@magek/jeparag",
"version": "0.0.11",
"description": "Native Joint Embedding Predictive Architecture (JEPA) + BM25 Hybrid RAG engine for Magek Ambient Agents",
"keywords": [
"magek",
"jepa",
"rag",
"hybrid-search",
"ambient-agents",
"event-sourcing"
],
"author": "Theam",
"homepage": "https://magek.ai",
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
},
"main": "dist/index.js",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/theam/magek.git"
},
"scripts": {
"format": "prettier --write --ext '.js,.ts' **/*.ts **/*/*.ts",
"lint:check": "eslint \"**/*.ts\"",
"lint:fix": "eslint --quiet --fix \"**/*.ts\"",
"build": "tsc -b tsconfig.json",
"clean": "rimraf ./dist ./dist-test tsconfig.tsbuildinfo",
"demo": "tsx examples/hipaa-audit-demo.ts",
"test": "tsc -b tsconfig.json && tsc -p tsconfig.test.json --outDir ./dist-test && mocha \"dist-test/test/**/*.test.js\" && rimraf ./dist-test",
"prepack": "tsc -b tsconfig.json"
},
"bugs": {
"url": "https://github.com/theam/magek/issues"
},
"engines": {
"node": ">=22.0.0 <23.0.0"
},
"dependencies": {
"@magek/common": "workspace:^0.0.11",
"@magek/core": "workspace:^0.0.11",
"tslib": "2.8.1",
"reflect-metadata": "0.2.2",
"uuid": "^13.0.0"
},
"devDependencies": {
"@magek/eslint-config": "workspace:^0.0.11",
"@types/chai": "5.2.3",
"@types/chai-as-promised": "8.0.2",
"@types/mocha": "10.0.10",
"@types/node": "22.19.9",
"@types/sinon": "21.0.0",
"@types/sinon-chai": "4.0.0",
"@types/uuid": "11.0.0",
"chai": "6.2.2",
"chai-as-promised": "8.0.2",
"mocha": "11.7.5",
"c8": "^10.1.3",
"rimraf": "6.1.2",
"sinon": "21.0.1",
"sinon-chai": "4.0.1",
"tsx": "^4.19.2",
"typescript": "5.9.3"
}
}
79 changes: 79 additions & 0 deletions packages/jeparag/src/agent/jeparag-agent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { DocumentLoader } from '../loader/pdf-loader'
import { JEPAEmbedder } from '../embedder/jepa-embedder'
import { DocumentIngestedEvent, ChunkEmbeddedEvent, JeparagQueryProcessedEvent } from '../concepts/events'
import { JeparagHybridSearchReadModel } from '../concepts/read-model'

export interface AgentQueryResult {
queryId: string
query: string
answer: string
contextChunks: string[]
rrfScores: number[]
}

/**
* Magek Ambient Agent for Jeparag.
* Reacts asynchronously to document ingestion events, indexes chunks in ReadModels,
* and handles contextual RAG generation queries.
*/
export class JeparagAmbientAgent {
private readonly embedder: JEPAEmbedder

constructor(embedderProvider: 'gemini' | 'openai' | 'hash' = 'hash') {
this.embedder = new JEPAEmbedder({ provider: embedderProvider })
}

/**
* Reaction handler when a DocumentIngestedEvent occurs in the system stream.
* Splits document into chunks, embeds them, and registers them into the hybrid ReadModel.
*/
public async onDocumentIngested(event: DocumentIngestedEvent): Promise<ChunkEmbeddedEvent[]> {
const chunks = DocumentLoader.chunkText(event.documentId, event.rawText, {
chunkSize: 256,
chunkOverlap: 50,
})

const events: ChunkEmbeddedEvent[] = []

for (const chunk of chunks) {
const embedding = await this.embedder.embedText(chunk.text)
const embeddedEvent = new ChunkEmbeddedEvent(
chunk.id,
chunk.documentId,
chunk.chunkIndex,
chunk.text,
embedding
)

// Project into Magek ReadModel
JeparagHybridSearchReadModel.projectChunkEmbedded(embeddedEvent)
events.push(embeddedEvent)
}

return events
}

/**
* Processes a user/agent query against the indexed corpus using RRF Hybrid search.
*/
public async processQuery(queryId: string, queryText: string, topK = 5): Promise<JeparagQueryProcessedEvent> {
const searchResults = await JeparagHybridSearchReadModel.queryHybrid(queryText, topK)

const contextTexts = searchResults.map((r) => r.chunk.text)
const contextIds = searchResults.map((r) => r.chunk.id)

// Build RAG answer synthesis
const answer = this.synthesizeAnswer(queryText, contextTexts)

return new JeparagQueryProcessedEvent(queryId, queryText, contextIds, answer)
}

private synthesizeAnswer(query: string, contexts: string[]): string {
if (contexts.length === 0) {
return `No relevant context found for query: "${query}".`
}

const compiledContext = contexts.map((ctx, i) => `[Context ${i + 1}]: ${ctx}`).join('\n\n')
return `[Jeparag RAG Answer]\nBased on ${contexts.length} retrieved context passages:\n\n${compiledContext}`
}
}
Loading
Loading