-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquery.js
More file actions
70 lines (60 loc) · 2.44 KB
/
query.js
File metadata and controls
70 lines (60 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// query.js — CLI chat (now conversational) across all DBs or a specific one (arg)
require("dotenv").config();
const readline = require("readline");
const path = require("path");
const { ensureModels } = require("./lib/models");
const retriever = require("./lib/retriever");
const convo = require("./lib/conversation"); // NEW
const llm = require("./lib/llmRunner"); // optional fallback
(async function main(){
await ensureModels([process.env.EMB_MODEL || "nomic-embed-text", process.env.GEN_MODEL || "qwen2.5:1.5b"]);
const argDb = process.argv[2] || null;
// discoverDbNames may be in retriever; if not, just show arg or "all"
const list = (typeof retriever.discoverDbNames === "function") ? retriever.discoverDbNames() : [];
console.log(`Loaded DBs: ${argDb ? argDb : (list.length ? list.join(", ") : "all")}`);
console.log("Type 'exit' to quit.");
// adapter for conversation.js
const retrieverAdapter = {
async search(query, opts) {
if (typeof retriever.search === "function") {
return retriever.search(query, opts);
}
const res = await retriever.answerOnce(query, argDb);
return (res.hits || []).map(h => ({
text: h.text || h.doc || "",
score: typeof h.score === "number" ? h.score : (h.sim || 0),
meta: { source: h.source, title: h.title, chunk: h.chunk_id }
}));
}
};
// optional LLM init
if (llm && typeof llm.init === "function") {
try { await llm.init(); } catch {/* ignore */}
}
const state = convo.initState();
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const askOnce = () => rl.question("\nAsk: ", async (qt)=>{
try {
if (!qt) return askOnce();
if (qt.toLowerCase() === "exit") { rl.close(); process.exit(0); }
const res = await convo.answerTurn(
state,
qt,
retrieverAdapter,
llm, // used only if retrieval returns nothing
{ topK: 5, threshold: 0.38 } // tune as desired
);
console.log("\n--- Answer ---\n" + res.text);
console.log("\n--- Sources ---");
(res.hits || []).forEach(h => {
const src = (h.meta?.title || h.meta?.source || "doc");
const s = typeof h.score === "number" ? h.score.toFixed(3) : "n/a";
console.log(`• ${src} (sim≈${s})`);
});
} catch (e) {
console.error("Error:", e?.message || e);
}
askOnce();
});
askOnce();
})();