@wei840222/qmd 2026.9.27 → 2026.9.28
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/dist/cli/build-info.json +2 -2
- package/dist/hybrid.d.ts +2 -0
- package/dist/hybrid.js +15 -0
- package/dist/llm.d.ts +2 -0
- package/dist/remote-jev.d.ts +4 -0
- package/dist/remote-jev.js +53 -22
- package/dist/remote-llm.d.ts +2 -0
- package/dist/remote-llm.js +6 -0
- package/dist/store.js +11 -3
- package/package.json +1 -1
package/dist/cli/build-info.json
CHANGED
package/dist/hybrid.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export declare class Hybrid implements LLM {
|
|
|
11
11
|
get local(): LLM;
|
|
12
12
|
get supportsExpand(): boolean;
|
|
13
13
|
get supportsRerank(): boolean;
|
|
14
|
+
get rerankModelName(): string | undefined;
|
|
15
|
+
get generateModelName(): string | undefined;
|
|
14
16
|
embed(text: string, options?: EmbedOptions): Promise<EmbeddingResult | null>;
|
|
15
17
|
generate(prompt: string, options?: GenerateOptions): Promise<GenerateResult | null>;
|
|
16
18
|
modelExists(model: string): Promise<ModelInfo>;
|
package/dist/hybrid.js
CHANGED
|
@@ -22,6 +22,21 @@ export class Hybrid {
|
|
|
22
22
|
get supportsRerank() {
|
|
23
23
|
return Boolean(this.remoteJev?.supportsRerank || this.remoteLLM?.supportsRerank);
|
|
24
24
|
}
|
|
25
|
+
get rerankModelName() {
|
|
26
|
+
if (this.remoteJev?.supportsRerank) {
|
|
27
|
+
return this.remoteJev.rerankModelName;
|
|
28
|
+
}
|
|
29
|
+
if (this.remoteLLM?.supportsRerank && this.remoteLLM.rerankModelName) {
|
|
30
|
+
return this.remoteLLM.rerankModelName;
|
|
31
|
+
}
|
|
32
|
+
return this.localLLM.rerankModelName;
|
|
33
|
+
}
|
|
34
|
+
get generateModelName() {
|
|
35
|
+
if (this.remoteLLM?.supportsExpand && this.remoteLLM.generateModelName) {
|
|
36
|
+
return this.remoteLLM.generateModelName;
|
|
37
|
+
}
|
|
38
|
+
return this.localLLM.generateModelName;
|
|
39
|
+
}
|
|
25
40
|
async embed(text, options) {
|
|
26
41
|
return this.localLLM.embed(text, options);
|
|
27
42
|
}
|
package/dist/llm.d.ts
CHANGED
package/dist/remote-jev.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TypeSafeClient } from "@typesafe-ai/sdk";
|
|
2
2
|
import type { RerankDocument, RerankOptions, RerankResult, SearchIntentGuidance } from "./llm.js";
|
|
3
3
|
export declare const DEFAULT_JEV_TIMEOUT_MS = 30000;
|
|
4
|
+
export declare const DEFAULT_JEV_RERANK_BATCH_SIZE = 40;
|
|
4
5
|
export interface JevSystemOneClient {
|
|
5
6
|
systemOne(request: any, options?: any): Promise<any>;
|
|
6
7
|
}
|
|
@@ -9,6 +10,7 @@ export interface RemoteJevOptions {
|
|
|
9
10
|
baseUrl?: string;
|
|
10
11
|
model?: string;
|
|
11
12
|
concurrency?: number;
|
|
13
|
+
batchSize?: number;
|
|
12
14
|
timeoutMs?: number;
|
|
13
15
|
client?: TypeSafeClient | JevSystemOneClient;
|
|
14
16
|
}
|
|
@@ -24,10 +26,12 @@ export interface JevIntentClassification {
|
|
|
24
26
|
export declare class RemoteJev {
|
|
25
27
|
readonly model: string;
|
|
26
28
|
readonly concurrency: number;
|
|
29
|
+
readonly batchSize: number;
|
|
27
30
|
readonly client: TypeSafeClient | JevSystemOneClient;
|
|
28
31
|
constructor(options?: RemoteJevOptions);
|
|
29
32
|
get supportsRerank(): boolean;
|
|
30
33
|
get supportsExpand(): boolean;
|
|
34
|
+
get rerankModelName(): string;
|
|
31
35
|
resetCircuitBreaker(): void;
|
|
32
36
|
classifyIntent(query: string, options?: {
|
|
33
37
|
context?: string;
|
package/dist/remote-jev.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TypeSafeClient, choice, noul } from "@typesafe-ai/sdk";
|
|
2
2
|
import { getFormattedLocalTime } from "./remote-llm.js";
|
|
3
3
|
export const DEFAULT_JEV_TIMEOUT_MS = 30000;
|
|
4
|
+
export const DEFAULT_JEV_RERANK_BATCH_SIZE = 40;
|
|
4
5
|
export const JEV_STRATEGY_PLAYBOOK = {
|
|
5
6
|
code_search: {
|
|
6
7
|
label: "Code Search",
|
|
@@ -30,10 +31,12 @@ export const JEV_STRATEGY_PLAYBOOK = {
|
|
|
30
31
|
export class RemoteJev {
|
|
31
32
|
model;
|
|
32
33
|
concurrency;
|
|
34
|
+
batchSize;
|
|
33
35
|
client;
|
|
34
36
|
constructor(options = {}) {
|
|
35
37
|
this.model = options.model?.trim() || "jev-1.13";
|
|
36
38
|
this.concurrency = options.concurrency ?? 10;
|
|
39
|
+
this.batchSize = options.batchSize ?? DEFAULT_JEV_RERANK_BATCH_SIZE;
|
|
37
40
|
if (options.client) {
|
|
38
41
|
this.client = options.client;
|
|
39
42
|
}
|
|
@@ -54,6 +57,9 @@ export class RemoteJev {
|
|
|
54
57
|
get supportsExpand() {
|
|
55
58
|
return true;
|
|
56
59
|
}
|
|
60
|
+
get rerankModelName() {
|
|
61
|
+
return `jev:${this.model}`;
|
|
62
|
+
}
|
|
57
63
|
resetCircuitBreaker() {
|
|
58
64
|
// Kept for interface compatibility; error handling is handled per-request in caller/fallback
|
|
59
65
|
}
|
|
@@ -92,38 +98,63 @@ export class RemoteJev {
|
|
|
92
98
|
if (documents.length === 0) {
|
|
93
99
|
return { results: [], model: `jev:${this.model}` };
|
|
94
100
|
}
|
|
95
|
-
const
|
|
101
|
+
const state = { query };
|
|
102
|
+
const timeZone = typeof options === "object" && options !== null ? options.timeZone : undefined;
|
|
103
|
+
state.current_time = getFormattedLocalTime(new Date(), timeZone);
|
|
104
|
+
if (typeof options === "object" && options !== null && options.context) {
|
|
105
|
+
state.context = options.context;
|
|
106
|
+
}
|
|
107
|
+
const criteria = {
|
|
96
108
|
true: "The candidate directly addresses the query's specific question, requirement, or topic, satisfying any time or entity constraints.",
|
|
97
109
|
false: "The candidate is only on a similar topic, outside the requested time window, or unrelated to the query's specific need.",
|
|
98
|
-
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
};
|
|
111
|
+
const batches = [];
|
|
112
|
+
for (let offset = 0; offset < documents.length; offset += this.batchSize) {
|
|
113
|
+
batches.push({ docs: documents.slice(offset, offset + this.batchSize), offset });
|
|
114
|
+
}
|
|
115
|
+
const batchResults = await pMap(batches, async ({ docs: batchDocs, offset }) => {
|
|
116
|
+
const questions = {};
|
|
117
|
+
for (let i = 0; i < batchDocs.length; i++) {
|
|
118
|
+
const doc = batchDocs[i];
|
|
119
|
+
const text = typeof doc === "string" ? doc : doc.text;
|
|
120
|
+
const candidate = truncateCandidateText(text, 1500);
|
|
121
|
+
const instructions = {
|
|
122
|
+
candidate,
|
|
123
|
+
question: "Does `candidate` directly answer or address the search query in `query`?",
|
|
124
|
+
};
|
|
125
|
+
if (typeof doc !== "string" && doc.title) {
|
|
126
|
+
instructions.title = doc.title;
|
|
127
|
+
}
|
|
128
|
+
if (typeof doc !== "string" && doc.file) {
|
|
129
|
+
instructions.file = doc.file;
|
|
130
|
+
}
|
|
131
|
+
questions[`cand_${i}`] = noul(instructions, criteria);
|
|
109
132
|
}
|
|
110
|
-
const timeZone = typeof options === "object" && options !== null ? options.timeZone : undefined;
|
|
111
|
-
state.current_time = getFormattedLocalTime(new Date(), timeZone);
|
|
112
133
|
const response = await this.client.systemOne({
|
|
113
134
|
state,
|
|
114
135
|
model: this.model,
|
|
115
|
-
questions
|
|
136
|
+
questions,
|
|
116
137
|
});
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
138
|
+
const results = [];
|
|
139
|
+
for (let i = 0; i < batchDocs.length; i++) {
|
|
140
|
+
const doc = batchDocs[i];
|
|
141
|
+
const file = typeof doc === "string" ? doc : doc.file;
|
|
142
|
+
const key = `cand_${i}`;
|
|
143
|
+
const answer = response?.answers?.[key];
|
|
144
|
+
const score = typeof answer?.noul === "number" ? answer.noul : 0;
|
|
145
|
+
results.push({
|
|
146
|
+
file,
|
|
147
|
+
score,
|
|
148
|
+
index: offset + i,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return results;
|
|
122
152
|
}, this.concurrency);
|
|
153
|
+
const flattened = batchResults.flat();
|
|
123
154
|
// Sort by score descending
|
|
124
|
-
|
|
155
|
+
flattened.sort((a, b) => b.score - a.score);
|
|
125
156
|
return {
|
|
126
|
-
results,
|
|
157
|
+
results: flattened,
|
|
127
158
|
model: `jev:${this.model}`,
|
|
128
159
|
};
|
|
129
160
|
}
|
package/dist/remote-llm.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ export declare class RemoteLLM implements LLM {
|
|
|
33
33
|
constructor(options: RemoteLLMOptions);
|
|
34
34
|
get supportsExpand(): boolean;
|
|
35
35
|
get supportsRerank(): boolean;
|
|
36
|
+
get rerankModelName(): string | undefined;
|
|
37
|
+
get generateModelName(): string | undefined;
|
|
36
38
|
embed(_text: string, _options?: EmbedOptions): Promise<EmbeddingResult | null>;
|
|
37
39
|
generate(_prompt: string, _options?: GenerateOptions): Promise<GenerateResult | null>;
|
|
38
40
|
modelExists(_model: string): Promise<ModelInfo>;
|
package/dist/remote-llm.js
CHANGED
|
@@ -112,6 +112,12 @@ export class RemoteLLM {
|
|
|
112
112
|
get supportsRerank() {
|
|
113
113
|
return Boolean(this.rerankApiUrl && this.rerankApiModel && !this.rerankCircuitBroken);
|
|
114
114
|
}
|
|
115
|
+
get rerankModelName() {
|
|
116
|
+
return this.rerankApiModel;
|
|
117
|
+
}
|
|
118
|
+
get generateModelName() {
|
|
119
|
+
return this.generateApiModel;
|
|
120
|
+
}
|
|
115
121
|
async embed(_text, _options) {
|
|
116
122
|
// Embedding is handled separately by EmbeddingProvider
|
|
117
123
|
return null;
|
package/dist/store.js
CHANGED
|
@@ -2711,11 +2711,19 @@ export function createStore(dbPath, options = {}) {
|
|
|
2711
2711
|
searchFTS: (query, limit, collectionName, filter) => searchFTS(db, query, limit, collectionName, filter),
|
|
2712
2712
|
searchVec: (query, model, limit, collectionFilter, session, precomputedEmbedding, filter) => searchVec(db, query, model, limit, collectionFilter, session, precomputedEmbedding, store.embeddingProvider, store.authorizeRemoteRequest, store.llm, filter),
|
|
2713
2713
|
// Query expansion & reranking
|
|
2714
|
-
expandQuery: (query, model, expansionContext, options) =>
|
|
2715
|
-
|
|
2714
|
+
expandQuery: (query, model, expansionContext, options) => {
|
|
2715
|
+
const activeGenerateModel = store.llm?.generateModelName ?? store.localLlm?.generateModelName ?? DEFAULT_QUERY_MODEL;
|
|
2716
|
+
return expandQuery(query, model ?? activeGenerateModel, db, expansionContext, store.llm, options);
|
|
2717
|
+
},
|
|
2718
|
+
invalidateExpansionCache: (query, expansionContext, options) => {
|
|
2719
|
+
const activeGenerateModel = store.llm?.generateModelName ?? store.localLlm?.generateModelName ?? DEFAULT_QUERY_MODEL;
|
|
2720
|
+
return deleteExpansionCacheEntry(db, query, activeGenerateModel, expansionContext, options);
|
|
2721
|
+
},
|
|
2716
2722
|
rerank: (query, documents, model, rerankContext) => {
|
|
2717
2723
|
const llm = getLlm(store);
|
|
2718
|
-
|
|
2724
|
+
const activeLlm = store.llm ?? llm;
|
|
2725
|
+
const activeRerankModel = activeLlm?.rerankModelName ?? store.localLlm?.rerankModelName ?? llm?.rerankModelName ?? DEFAULT_RERANK_MODEL;
|
|
2726
|
+
return rerank(query, documents, model ?? activeRerankModel, db, rerankContext, activeLlm);
|
|
2719
2727
|
},
|
|
2720
2728
|
// Document retrieval
|
|
2721
2729
|
findDocument: (filename, options) => findDocument(db, filename, options),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wei840222/qmd",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.28",
|
|
4
4
|
"packageManager": "pnpm@11.15.1",
|
|
5
5
|
"description": "Query Markup Documents - On-device hybrid search for markdown files with BM25, vector search, and LLM reranking",
|
|
6
6
|
"type": "module",
|