knowy 1.0.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/README.md +108 -0
- package/knowy.js +116 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Knowy
|
|
2
|
+
|
|
3
|
+
A local-first, zero-config knowledge base engine with semantic vector search. Built on LanceDB and Hugging Face Transformers.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔍 **Semantic Search** - Find relevant content using natural language queries
|
|
8
|
+
- 💾 **Local-First** - All data stored locally using LanceDB (no cloud required)
|
|
9
|
+
- 🧠 **Built-in Embeddings** - Uses Qwen3-Embedding-0.6B-ONNX for high-quality vectors
|
|
10
|
+
- 📚 **Knowledge Base Organization** - Group data into named knowledge bases
|
|
11
|
+
- ❓ **Q&A Support** - Store question-answer pairs or free text documents
|
|
12
|
+
- 🚀 **Zero Configuration** - Works out of the box with sensible defaults
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install knowy
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
import { knowy } from 'knowy';
|
|
24
|
+
|
|
25
|
+
// Initialize the engine
|
|
26
|
+
const kbs = await knowy('./my_database');
|
|
27
|
+
|
|
28
|
+
// Create or access a knowledge base
|
|
29
|
+
const docs = kbs('documentation');
|
|
30
|
+
|
|
31
|
+
// Add Q&A pairs
|
|
32
|
+
await docs.addQA('getting-started', 'How do I install?', 'Run npm install knowy');
|
|
33
|
+
|
|
34
|
+
// Or add free text
|
|
35
|
+
await docs.addText('api-reference', 'The API supports vector search with cosine similarity...');
|
|
36
|
+
|
|
37
|
+
// Search across your knowledge base
|
|
38
|
+
const results = await docs.search('how to install this package?', { limit: 5 });
|
|
39
|
+
console.log(results);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## API Reference
|
|
43
|
+
|
|
44
|
+
### `knowy(dbPath)`
|
|
45
|
+
|
|
46
|
+
Initialize the Knowy engine.
|
|
47
|
+
|
|
48
|
+
- `dbPath` (string): Path to the LanceDB database directory (default: `\"./knowy_database\"`)
|
|
49
|
+
|
|
50
|
+
Returns a `kbs` function with attached methods.
|
|
51
|
+
|
|
52
|
+
### `kbs(kbName)`
|
|
53
|
+
|
|
54
|
+
Get or create a knowledge base.
|
|
55
|
+
|
|
56
|
+
Returns a knowledge base object with methods:
|
|
57
|
+
- `addQA(topic, question, answer)` - Add a Q&A pair
|
|
58
|
+
- `addText(topic, text)` - Add free text content
|
|
59
|
+
- `search(query, options)` - Search within this KB
|
|
60
|
+
- `delete()` - Delete this knowledge base
|
|
61
|
+
|
|
62
|
+
### `kbs.search(query, options)`
|
|
63
|
+
|
|
64
|
+
Search across all knowledge bases.
|
|
65
|
+
|
|
66
|
+
- `query` (string): Search query
|
|
67
|
+
- `options.kbs` (string|string[]): Filter by specific knowledge base(s)
|
|
68
|
+
- `options.limit` (number): Max results (default: 10)
|
|
69
|
+
|
|
70
|
+
Returns array of results with `kb`, `topic`, `type`, `content`, and `score` (0-1).
|
|
71
|
+
|
|
72
|
+
### `kbs.list()`
|
|
73
|
+
|
|
74
|
+
List all knowledge bases.
|
|
75
|
+
|
|
76
|
+
## Example: Multi-KB Setup
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
const kbs = await knowy();
|
|
80
|
+
|
|
81
|
+
// Separate KBs for different domains
|
|
82
|
+
const codeKB = kbs('code-snippets');
|
|
83
|
+
const docsKB = kbs('documentation');
|
|
84
|
+
const supportKB = kbs('support-tickets');
|
|
85
|
+
|
|
86
|
+
// Add content to each...
|
|
87
|
+
await codeKB.addText('auth', 'JWT authentication implementation...');
|
|
88
|
+
await docsKB.addQA('setup', 'Node version?', 'Requires Node 18+');
|
|
89
|
+
await supportKB.addQA('billing', 'How to cancel?', 'Go to settings > billing...');
|
|
90
|
+
|
|
91
|
+
// Search everything
|
|
92
|
+
const allResults = await kbs.search('authentication', { limit: 10 });
|
|
93
|
+
|
|
94
|
+
// Search specific KBs only
|
|
95
|
+
const codeOnly = await kbs.search('authentication', { kbs: 'code-snippets' });
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Search Scoring
|
|
99
|
+
|
|
100
|
+
Results include a `score` from 0 to 1, where 1 is a perfect match. The score is calculated using cosine similarity between the query embedding and stored vectors.
|
|
101
|
+
|
|
102
|
+
## Requirements
|
|
103
|
+
|
|
104
|
+
- Node.js >= 18.0.0
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT © littlejustnode
|
package/knowy.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { pipeline } from '@huggingface/transformers';
|
|
2
|
+
import * as lancedb from "@lancedb/lancedb";
|
|
3
|
+
import crypto from "crypto";
|
|
4
|
+
|
|
5
|
+
class KnowyEngine {
|
|
6
|
+
constructor(dbPath) {
|
|
7
|
+
this.dbPath = dbPath;
|
|
8
|
+
this.modelId = 'onnx-community/Qwen3-Embedding-0.6B-ONNX';
|
|
9
|
+
this.tableName = "all_knowledge_records";
|
|
10
|
+
this.extractor = null;
|
|
11
|
+
this.db = null;
|
|
12
|
+
this.table = null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async init() {
|
|
16
|
+
this.extractor = await pipeline('feature-extraction', this.modelId, { dtype: 'fp32' });
|
|
17
|
+
this.db = await lancedb.connect(this.dbPath);
|
|
18
|
+
const tableNames = await this.db.tableNames();
|
|
19
|
+
if (tableNames.includes(this.tableName)) {
|
|
20
|
+
this.table = await this.db.openTable(this.tableName);
|
|
21
|
+
}
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async _getEmbedding(text) {
|
|
26
|
+
const output = await this.extractor(text, { pooling: 'last_token', normalize: true });
|
|
27
|
+
return Array.from(output.data);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async _upsert(record) {
|
|
31
|
+
if (!this.table) {
|
|
32
|
+
this.table = await this.db.createTable(this.tableName, [record]);
|
|
33
|
+
} else {
|
|
34
|
+
await this.table.add([record]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getKB(kbName) {
|
|
39
|
+
return {
|
|
40
|
+
name: kbName,
|
|
41
|
+
addQA: (topic, q, a) => this.addQA(kbName, topic, q, a),
|
|
42
|
+
addText: (topic, text) => this.addText(kbName, topic, text),
|
|
43
|
+
search: (query, options = {}) => this.search(query, { ...options, kbs: kbName }),
|
|
44
|
+
delete: () => this.deleteKB(kbName)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async addQA(kbName, topic, question, answer) {
|
|
49
|
+
const vector = await this._getEmbedding(question);
|
|
50
|
+
await this._upsert({
|
|
51
|
+
id: crypto.randomUUID(),
|
|
52
|
+
vector, kb_name: kbName, topic, type: 'qa',
|
|
53
|
+
question, answer, text: "", created_at: new Date().toISOString()
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async addText(kbName, topic, text) {
|
|
58
|
+
const vector = await this._getEmbedding(text);
|
|
59
|
+
await this._upsert({
|
|
60
|
+
id: crypto.randomUUID(),
|
|
61
|
+
vector, kb_name: kbName, topic, type: 'text',
|
|
62
|
+
question: "", answer: "", text, created_at: new Date().toISOString()
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async search(query, options = {}) {
|
|
67
|
+
if (!this.table) return [];
|
|
68
|
+
const { kbs, limit = 10 } = options;
|
|
69
|
+
const queryVector = await this._getEmbedding(query);
|
|
70
|
+
let request = this.table.vectorSearch(queryVector);
|
|
71
|
+
request.metricType = "cosine";
|
|
72
|
+
|
|
73
|
+
if (kbs) {
|
|
74
|
+
const filter = Array.isArray(kbs)
|
|
75
|
+
? `kb_name IN (${kbs.map(n => `"${n}"`).join(",")})`
|
|
76
|
+
: `kb_name = "${kbs}"`;
|
|
77
|
+
request = request.where(filter);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const results = await request.limit(limit).toArray();
|
|
81
|
+
return results.map(r => ({
|
|
82
|
+
kb: r.kb_name,
|
|
83
|
+
topic: r.topic,
|
|
84
|
+
type: r.type,
|
|
85
|
+
content: r.type === 'qa' ? { q: r.question, a: r.answer } : { text: r.text },
|
|
86
|
+
score: 1-(r._distance/2)
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async deleteKB(kbName) {
|
|
91
|
+
if (this.table) await this.table.delete(`kb_name = "${kbName}"`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async listKBs() {
|
|
95
|
+
if (!this.table) return [];
|
|
96
|
+
const all = await this.table.query().select(["kb_name"]).toArray();
|
|
97
|
+
return [...new Set(all.map(i => i.kb_name))];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Main export: initializes engine and returns the kbs function.
|
|
103
|
+
*/
|
|
104
|
+
export const knowy = async (dbPath = "./knowy_database") => {
|
|
105
|
+
const engine = new KnowyEngine(dbPath);
|
|
106
|
+
await engine.init();
|
|
107
|
+
|
|
108
|
+
// The kbs function
|
|
109
|
+
const kbs = (kbName) => engine.getKB(kbName);
|
|
110
|
+
|
|
111
|
+
// Attached methods
|
|
112
|
+
kbs.search = (query, options) => engine.search(query, options);
|
|
113
|
+
kbs.list = () => engine.listKBs();
|
|
114
|
+
|
|
115
|
+
return kbs;
|
|
116
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "knowy",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A local-first knowledge base engine with vector search using LanceDB and Hugging Face embeddings",
|
|
5
|
+
"main": "knowy.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"knowledge-base",
|
|
12
|
+
"vector-search",
|
|
13
|
+
"embeddings",
|
|
14
|
+
"lancedb",
|
|
15
|
+
"huggingface",
|
|
16
|
+
"semantic-search",
|
|
17
|
+
"qa",
|
|
18
|
+
"ai",
|
|
19
|
+
"knowy",
|
|
20
|
+
"local-first"
|
|
21
|
+
],
|
|
22
|
+
"author": "littlejustnode",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/littlejustnode/knowy.git"
|
|
27
|
+
},
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/littlejustnode/knowy/issues"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/littlejustnode/knowy#readme",
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@huggingface/transformers": "^3.0.0",
|
|
34
|
+
"@lancedb/lancedb": "^0.15.0"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
}
|
|
39
|
+
}
|