@o-lang/semantic-doc-search 1.0.40 → 1.0.42
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 +17 -12
- package/package.json +37 -38
- package/src/embeddings/local.js +12 -2
- package/src/embeddings/local.js.bak +153 -0
- package/src/index.js +1 -1
- package/src/resolver.js +59 -179
- package/src/services/docQA.js +56 -19
- package/src/utils/formatResults.js +9 -10
- package/.cache/embeddings/Xenova/all-MiniLM-L6-v2/config.json +0 -25
- package/.cache/embeddings/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
- package/.cache/embeddings/Xenova/all-MiniLM-L6-v2/tokenizer.json +0 -30686
- package/.cache/embeddings/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +0 -15
- package/.env.example +0 -0
- package/bin/cli.js +0 -58
- package/docs/sample1.txt +0 -1
- package/docs/vacation policy +0 -5
- package/embeddings.json +0 -3
- package/test-doc-search-batch.js +0 -36
- package/test-doc-search.js +0 -40
- package/test-embed.js +0 -10
- package/test-single-doc.js +0 -32
package/src/services/docQA.js
CHANGED
|
@@ -2,20 +2,22 @@ const VectorRouter = require("../adapters/vectorRouter");
|
|
|
2
2
|
const embedder = require("../embeddings/local");
|
|
3
3
|
const extractText = require("../utils/extractText");
|
|
4
4
|
const chunkText = require("../utils/chunker");
|
|
5
|
+
const formatResults = require("../utils/formatResults");
|
|
5
6
|
const fs = require("fs");
|
|
6
7
|
const path = require("path");
|
|
7
8
|
|
|
8
9
|
async function performDocQA(
|
|
9
10
|
query,
|
|
10
11
|
{
|
|
11
|
-
doc_root,
|
|
12
|
-
vectorBackend = "
|
|
12
|
+
doc_root = "./docs",
|
|
13
|
+
vectorBackend = "memory", // 🔥 default to memory like Python fallback
|
|
13
14
|
dimension = 384,
|
|
14
|
-
migrate_on_demand = false,
|
|
15
15
|
POSTGRES_URL,
|
|
16
|
+
topK = 5,
|
|
16
17
|
...config
|
|
17
18
|
} = {}
|
|
18
19
|
) {
|
|
20
|
+
// ── Create vector store
|
|
19
21
|
const store = VectorRouter.create({
|
|
20
22
|
backend: vectorBackend,
|
|
21
23
|
dimension,
|
|
@@ -25,30 +27,65 @@ async function performDocQA(
|
|
|
25
27
|
|
|
26
28
|
const embed = await embedder({ dimension });
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
// ─────────────────────────────────────────────
|
|
31
|
+
// 🔥 ALWAYS INGEST (Python parity)
|
|
32
|
+
// ─────────────────────────────────────────────
|
|
33
|
+
if (doc_root && fs.existsSync(doc_root)) {
|
|
34
|
+
const files = fs.readdirSync(doc_root);
|
|
35
|
+
|
|
36
|
+
for (const file of files) {
|
|
30
37
|
const fullPath = path.join(doc_root, file);
|
|
38
|
+
|
|
31
39
|
if (!fs.statSync(fullPath).isFile()) continue;
|
|
40
|
+
if (!file.endsWith(".txt") && !file.endsWith(".md")) continue;
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const text = await extractText(fullPath);
|
|
44
|
+
if (!text || !text.trim()) continue;
|
|
45
|
+
|
|
46
|
+
const chunks = chunkText(text, 500, 50) || [text];
|
|
47
|
+
|
|
48
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
49
|
+
const chunk = chunks[i];
|
|
50
|
+
if (!chunk.trim()) continue;
|
|
32
51
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
try {
|
|
53
|
+
await store.upsert({
|
|
54
|
+
id: `${file}:${i}`,
|
|
55
|
+
vector: await embed(chunk),
|
|
56
|
+
content: chunk,
|
|
57
|
+
source: `file:${file}`,
|
|
58
|
+
metadata: { chunk: i }
|
|
59
|
+
});
|
|
60
|
+
} catch (err) {
|
|
61
|
+
console.warn("⚠️ Chunk failed:", err.message);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
} catch (err) {
|
|
66
|
+
console.error("❌ Failed to process file:", file, err.message);
|
|
44
67
|
}
|
|
45
68
|
}
|
|
46
69
|
}
|
|
47
70
|
|
|
48
|
-
|
|
71
|
+
// ─────────────────────────────────────────────
|
|
72
|
+
// 🔍 SEARCH
|
|
73
|
+
// ─────────────────────────────────────────────
|
|
74
|
+
let matches = [];
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const queryVector = await embed(query);
|
|
78
|
+
matches = await store.query(queryVector, { topK });
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.error("❌ Search failed:", err.message);
|
|
81
|
+
}
|
|
49
82
|
|
|
50
83
|
if (store.close) await store.close();
|
|
51
|
-
|
|
84
|
+
|
|
85
|
+
// ─────────────────────────────────────────────
|
|
86
|
+
// ✅ FORMAT LIKE PYTHON
|
|
87
|
+
// ─────────────────────────────────────────────
|
|
88
|
+
return formatResults(matches, query);
|
|
52
89
|
}
|
|
53
90
|
|
|
54
|
-
module.exports = performDocQA;
|
|
91
|
+
module.exports = performDocQA;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
function formatResults(results = [], query = "") {
|
|
2
|
+
const safeResults = Array.isArray(results) ? results : [];
|
|
3
|
+
|
|
4
|
+
const text = safeResults.length
|
|
5
|
+
? safeResults.map(r => r.content).join('\n\n')
|
|
6
|
+
: "";
|
|
7
|
+
|
|
9
8
|
return {
|
|
10
9
|
query,
|
|
11
|
-
text,
|
|
12
|
-
matches:
|
|
10
|
+
text,
|
|
11
|
+
matches: safeResults.map(r => ({
|
|
13
12
|
id: r.id,
|
|
14
13
|
content: r.content,
|
|
15
14
|
source: r.source,
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"_name_or_path": "sentence-transformers/all-MiniLM-L6-v2",
|
|
3
|
-
"architectures": [
|
|
4
|
-
"BertModel"
|
|
5
|
-
],
|
|
6
|
-
"attention_probs_dropout_prob": 0.1,
|
|
7
|
-
"classifier_dropout": null,
|
|
8
|
-
"gradient_checkpointing": false,
|
|
9
|
-
"hidden_act": "gelu",
|
|
10
|
-
"hidden_dropout_prob": 0.1,
|
|
11
|
-
"hidden_size": 384,
|
|
12
|
-
"initializer_range": 0.02,
|
|
13
|
-
"intermediate_size": 1536,
|
|
14
|
-
"layer_norm_eps": 1e-12,
|
|
15
|
-
"max_position_embeddings": 512,
|
|
16
|
-
"model_type": "bert",
|
|
17
|
-
"num_attention_heads": 12,
|
|
18
|
-
"num_hidden_layers": 6,
|
|
19
|
-
"pad_token_id": 0,
|
|
20
|
-
"position_embedding_type": "absolute",
|
|
21
|
-
"transformers_version": "4.29.2",
|
|
22
|
-
"type_vocab_size": 2,
|
|
23
|
-
"use_cache": true,
|
|
24
|
-
"vocab_size": 30522
|
|
25
|
-
}
|
|
Binary file
|