@llangtop/pwiki-core 0.3.4 → 0.4.5

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.
Files changed (141) hide show
  1. package/dist/WikiEngine.d.ts +25 -37
  2. package/dist/WikiEngine.d.ts.map +1 -1
  3. package/dist/WikiEngine.js +157 -298
  4. package/dist/WikiEngine.js.map +1 -1
  5. package/dist/ast-chunker.d.ts +23 -0
  6. package/dist/ast-chunker.d.ts.map +1 -0
  7. package/dist/ast-chunker.js +434 -0
  8. package/dist/ast-chunker.js.map +1 -0
  9. package/dist/content-cache.d.ts +13 -0
  10. package/dist/content-cache.d.ts.map +1 -0
  11. package/dist/content-cache.js +33 -0
  12. package/dist/content-cache.js.map +1 -0
  13. package/dist/embedder.d.ts +38 -0
  14. package/dist/embedder.d.ts.map +1 -0
  15. package/dist/embedder.js +267 -0
  16. package/dist/embedder.js.map +1 -0
  17. package/dist/file-manifest.d.ts +46 -0
  18. package/dist/file-manifest.d.ts.map +1 -0
  19. package/dist/file-manifest.js +121 -0
  20. package/dist/file-manifest.js.map +1 -0
  21. package/dist/index.d.ts +18 -8
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +25 -7
  24. package/dist/index.js.map +1 -1
  25. package/dist/indexer-compile.d.ts +20 -0
  26. package/dist/indexer-compile.d.ts.map +1 -0
  27. package/dist/indexer-compile.js +198 -0
  28. package/dist/indexer-compile.js.map +1 -0
  29. package/dist/indexer-embed.d.ts +21 -0
  30. package/dist/indexer-embed.d.ts.map +1 -0
  31. package/dist/indexer-embed.js +248 -0
  32. package/dist/indexer-embed.js.map +1 -0
  33. package/dist/indexer-scan.d.ts +4 -0
  34. package/dist/indexer-scan.d.ts.map +1 -0
  35. package/dist/indexer-scan.js +51 -0
  36. package/dist/indexer-scan.js.map +1 -0
  37. package/dist/indexer.d.ts +4 -0
  38. package/dist/indexer.d.ts.map +1 -0
  39. package/dist/indexer.js +7 -0
  40. package/dist/indexer.js.map +1 -0
  41. package/dist/model-registry.d.ts +32 -0
  42. package/dist/model-registry.d.ts.map +1 -0
  43. package/dist/model-registry.js +82 -0
  44. package/dist/model-registry.js.map +1 -0
  45. package/dist/parser.d.ts +9 -0
  46. package/dist/parser.d.ts.map +1 -0
  47. package/dist/parser.js +54 -0
  48. package/dist/parser.js.map +1 -0
  49. package/dist/preprocessor.d.ts +36 -0
  50. package/dist/preprocessor.d.ts.map +1 -0
  51. package/dist/preprocessor.js +209 -0
  52. package/dist/preprocessor.js.map +1 -0
  53. package/dist/search.d.ts +6 -0
  54. package/dist/search.d.ts.map +1 -0
  55. package/dist/search.js +91 -0
  56. package/dist/search.js.map +1 -0
  57. package/dist/semantic-compiler.d.ts +44 -0
  58. package/dist/semantic-compiler.d.ts.map +1 -0
  59. package/dist/semantic-compiler.js +376 -0
  60. package/dist/semantic-compiler.js.map +1 -0
  61. package/dist/semantic-search.d.ts +11 -0
  62. package/dist/semantic-search.d.ts.map +1 -0
  63. package/dist/semantic-search.js +217 -0
  64. package/dist/semantic-search.js.map +1 -0
  65. package/dist/store-settings.d.ts +32 -0
  66. package/dist/store-settings.d.ts.map +1 -0
  67. package/dist/store-settings.js +138 -0
  68. package/dist/store-settings.js.map +1 -0
  69. package/dist/store-vectors.d.ts +13 -0
  70. package/dist/store-vectors.d.ts.map +1 -0
  71. package/dist/store-vectors.js +101 -0
  72. package/dist/store-vectors.js.map +1 -0
  73. package/dist/store.d.ts +11 -0
  74. package/dist/store.d.ts.map +1 -0
  75. package/dist/store.js +28 -0
  76. package/dist/store.js.map +1 -0
  77. package/dist/types.d.ts +75 -92
  78. package/dist/types.d.ts.map +1 -1
  79. package/dist/types.js +1 -1
  80. package/dist/types.js.map +1 -1
  81. package/dist/wiki-paths.d.ts +3 -0
  82. package/dist/wiki-paths.d.ts.map +1 -0
  83. package/dist/wiki-paths.js +13 -0
  84. package/dist/wiki-paths.js.map +1 -0
  85. package/package.json +38 -38
  86. package/dist/compile/compiler.d.ts +0 -39
  87. package/dist/compile/compiler.d.ts.map +0 -1
  88. package/dist/compile/compiler.js +0 -227
  89. package/dist/compile/compiler.js.map +0 -1
  90. package/dist/compile/index.d.ts +0 -3
  91. package/dist/compile/index.d.ts.map +0 -1
  92. package/dist/compile/index.js +0 -2
  93. package/dist/compile/index.js.map +0 -1
  94. package/dist/embed/WikiEmbedder.d.ts +0 -28
  95. package/dist/embed/WikiEmbedder.d.ts.map +0 -1
  96. package/dist/embed/WikiEmbedder.js +0 -147
  97. package/dist/embed/WikiEmbedder.js.map +0 -1
  98. package/dist/embed/index.d.ts +0 -2
  99. package/dist/embed/index.d.ts.map +0 -1
  100. package/dist/embed/index.js +0 -2
  101. package/dist/embed/index.js.map +0 -1
  102. package/dist/llm/WikiLLM.d.ts +0 -24
  103. package/dist/llm/WikiLLM.d.ts.map +0 -1
  104. package/dist/llm/WikiLLM.js +0 -46
  105. package/dist/llm/WikiLLM.js.map +0 -1
  106. package/dist/llm/index.d.ts +0 -3
  107. package/dist/llm/index.d.ts.map +0 -1
  108. package/dist/llm/index.js +0 -2
  109. package/dist/llm/index.js.map +0 -1
  110. package/dist/models.d.ts +0 -5
  111. package/dist/models.d.ts.map +0 -1
  112. package/dist/models.js +0 -54
  113. package/dist/models.js.map +0 -1
  114. package/dist/search/WikiSearch.d.ts +0 -14
  115. package/dist/search/WikiSearch.d.ts.map +0 -1
  116. package/dist/search/WikiSearch.js +0 -223
  117. package/dist/search/WikiSearch.js.map +0 -1
  118. package/dist/search/index.d.ts +0 -2
  119. package/dist/search/index.d.ts.map +0 -1
  120. package/dist/search/index.js +0 -2
  121. package/dist/search/index.js.map +0 -1
  122. package/dist/store/WikiStore.d.ts +0 -47
  123. package/dist/store/WikiStore.d.ts.map +0 -1
  124. package/dist/store/WikiStore.js +0 -301
  125. package/dist/store/WikiStore.js.map +0 -1
  126. package/dist/store/index.d.ts +0 -2
  127. package/dist/store/index.d.ts.map +0 -1
  128. package/dist/store/index.js +0 -2
  129. package/dist/store/index.js.map +0 -1
  130. package/dist/util/fs.d.ts +0 -7
  131. package/dist/util/fs.d.ts.map +0 -1
  132. package/dist/util/fs.js +0 -36
  133. package/dist/util/fs.js.map +0 -1
  134. package/dist/util/index.d.ts +0 -3
  135. package/dist/util/index.d.ts.map +0 -1
  136. package/dist/util/index.js +0 -3
  137. package/dist/util/index.js.map +0 -1
  138. package/dist/util/paths.d.ts +0 -17
  139. package/dist/util/paths.d.ts.map +0 -1
  140. package/dist/util/paths.js +0 -31
  141. package/dist/util/paths.js.map +0 -1
@@ -0,0 +1,376 @@
1
+ // semantic-compiler.ts — 语义编译器 prompt (v5.2)
2
+ //
3
+ // v5.2: 文件级编译为主,块级编译兜底。
4
+ // LLM 只做 4 件事: topic, normalizedText, concepts, aliases + 自判语义边界
5
+ // 程序做其余 7 件事 (→ preprocessor.ts)
6
+ //
7
+ // 蓝图参考: §24 Agent System Prompt, §25 User Prompt Template, §14 embedding_text
8
+ // ============================================================
9
+ // 常量
10
+ // ============================================================
11
+ /** 推荐每批处理的 chunk 数(平衡上下文大小和效率) */
12
+ export const BATCH_SIZE = 25;
13
+ // ============================================================
14
+ // System Prompt (蓝图 §24)
15
+ // ============================================================
16
+ export const COMPILE_SYSTEM_PROMPT = `你是一个"知识语义编译器"。
17
+
18
+ 你的任务不是总结内容。
19
+
20
+ 你的任务是:
21
+ 将人类随手记录的非结构化笔记,
22
+ 转换为适合机器语义索引、概念检索、
23
+ 知识聚类、长期演化的"认知知识单元"。
24
+
25
+ 核心原则:
26
+ 1. 保留原始信息 — 不删技术细节
27
+ 2. 不改变原意 — 只规范化表达
28
+ 3. 补全隐式表达 — 补充省略的主语、展开缩写
29
+ 4. 统一术语 — 将同义表达归一(如 "状态污染" ↔ "stale closure")
30
+ 5. 提取核心概念 — 识别技术关键词
31
+ 6. 保持单主题 — 一个 chunk 只描述一个认知主题
32
+ 7. 输出结构化 JSON — 严格遵循 schema
33
+
34
+ 禁止:
35
+ 1. 过度总结
36
+ 2. 删除原文
37
+ 3. 改写逻辑
38
+ 4. 主观推断
39
+ 5. 引入不存在的信息
40
+
41
+ 你的角色是:"语义标准化器",不是"内容作者"。`;
42
+ // ============================================================
43
+ // User Prompt 构建 (蓝图 §25)
44
+ // ============================================================
45
+ /** 为一批 chunk 构建编译 prompt */
46
+ export function buildCompilePrompt(chunks) {
47
+ const chunkBlocks = chunks
48
+ .map((c, i) => {
49
+ const contextLines = [
50
+ `--- CHUNK #${i + 1} ---`,
51
+ `KEY: ${c.key}`,
52
+ `FILE: ${c.relPath}`,
53
+ `HEADING: ${c.heading || "(无标题)"}`,
54
+ ];
55
+ // E2: 注入文件级上下文
56
+ if (c.fileTags?.length) {
57
+ contextLines.push(`FILE_TAGS: [${c.fileTags.join(", ")}]`);
58
+ }
59
+ if (c.headingPath) {
60
+ contextLines.push(`HEADING_PATH: ${c.headingPath}`);
61
+ }
62
+ if (c.siblingHeadings?.length) {
63
+ contextLines.push(`SIBLING_HEADINGS: [${c.siblingHeadings.join(" | ")}]`);
64
+ }
65
+ if (c.totalChunks && c.totalChunks > 1) {
66
+ const pos = `${(c.chunkIndex ?? 0) + 1}/${c.totalChunks}`;
67
+ const role = (c.chunkIndex ?? 0) === 0
68
+ ? " (开头)"
69
+ : (c.chunkIndex ?? 0) === c.totalChunks - 1
70
+ ? " (结尾)"
71
+ : " (中间)";
72
+ contextLines.push(`CHUNK_POSITION: ${pos}${role}`);
73
+ }
74
+ contextLines.push("", c.rawText);
75
+ return contextLines.join("\n");
76
+ })
77
+ .join("\n\n");
78
+ return `请分析以下 ${chunks.length} 个笔记块。
79
+
80
+ ## 上下文说明
81
+
82
+ 每个块附带以下上下文信息,请善用以理解块在文件和笔记体系中的位置:
83
+ - FILE_TAGS: 文件级别的标签,反映所属领域(如 AMI, DLMS)
84
+ - HEADING_PATH: 块的标题层级路径(如 "10.18AMI更新 > 排查过程")
85
+ - SIBLING_HEADINGS: 同一文件内所有块的标题,帮助你理解块之间的前后关系
86
+ - CHUNK_POSITION: 本块在文件中的位置和角色(开头/中间/结尾)
87
+
88
+ ## 输出字段
89
+
90
+ 对每个块,输出一个 JSON 对象,包含以下字段:
91
+
92
+ {
93
+ "key": "块标识(与输入的 KEY 一致)",
94
+ "topic": "核心主题(一句话)",
95
+ "summary": "一句话摘要(≤30 字)",
96
+ "concepts": ["提取的技术概念"],
97
+ "entities": ["实体名称"],
98
+ "aliases": ["同义表达,格式 '中文 ↔ English'"],
99
+ "keywords": ["检索关键词"],
100
+ "normalizedText": "规范化后的文本(补全省略、统一术语、保留所有技术细节)",
101
+ "chunkType": "concept | note | code | reference | todo | idea | question | architecture | decision | log | research",
102
+ "importance": 0.0-1.0,
103
+ "confidence": 0.0-1.0,
104
+ "contentClass": "knowledge | event | conversation | reference",
105
+ "temporalAnchor": "如果内容是事件类,提取时间锚点(如 '2024-10-18'),否则省略",
106
+ "followsChunk": "如果有 SIBLING_HEADINGS 且本块不是第一个,填写前一个块的 KEY",
107
+ "precedesChunk": "如果有 SIBLING_HEADINGS 且本块不是最后一个,填写后一个块的 KEY",
108
+ "siblingHeadings": ["同文件所有块的标题列表(复制 SIBLING_HEADINGS)"]
109
+ }
110
+
111
+ ## 关系字段判断指南
112
+
113
+ contentClass 判断:
114
+ - knowledge: 无时间性的技术知识、编码规范、原理说明
115
+ - event: 有时间锚点的故障记录、更新日志、会议记录
116
+ - conversation: 对话推理链中的片段(隐式引用前文)
117
+ - reference: 纯参考列表、配置清单、目录结构
118
+
119
+ followsChunk/precedesChunk:
120
+ - 仅在 SIBLING_HEADINGS 明确显示了前后顺序时填写
121
+ - 使用 CHUNK #N 中的 KEY 值
122
+ - 如果块之间无明显因果/时序关系,留空
123
+
124
+ temporalAnchor:
125
+ - 仅在 contentClass=event 时尝试提取
126
+ - 从 FILE_TAGS、HEADING_PATH 或文本本身提取日期
127
+ - 格式: YYYY-MM-DD,无法确定则留空
128
+
129
+ ## 注意事项
130
+
131
+ - normalizedText 必须保留 ALL 技术细节
132
+ - importance: 高价值技术知识 0.8+,TODO/碎片 0.3-,普通笔记 0.5
133
+ - confidence: 信息完整明确 0.9+,曖昧 0.5-
134
+ - 所有关系字段为可选 —— 如果无法判断,留空而非猜测
135
+
136
+ 返回格式:一个 JSON 数组,包含 ${chunks.length} 个对象。
137
+ 不要 markdown 代码块包裹,直接输出 JSON 数组。
138
+
139
+ ${chunkBlocks}`;
140
+ }
141
+ // ============================================================
142
+ // embeddingText 构建 (蓝图 §14)
143
+ // ============================================================
144
+ /**
145
+ * 从编译后的 ChunkInfo 构建最优 embedding 输入
146
+ *
147
+ * 蓝图推荐格式:
148
+ * [TOPIC] + [CONCEPTS] + [ALIASES] + [KEYWORDS] + [NORMALIZED] + [RAW]
149
+ *
150
+ * 原因: 增强隐式语义,让向量模型在检索时更稳定地匹配
151
+ */
152
+ export function buildEmbeddingText(topic, normalizedText, concepts, aliases, keywords, contentClass, temporalAnchor, rawText) {
153
+ const parts = [];
154
+ if (contentClass)
155
+ parts.push(`[CLASS] ${contentClass}`);
156
+ if (temporalAnchor)
157
+ parts.push(`[TIME] ${temporalAnchor}`);
158
+ if (topic)
159
+ parts.push(`[TOPIC] ${topic}`);
160
+ if (concepts?.length)
161
+ parts.push(`[CONCEPTS] ${concepts.join("; ")}`);
162
+ if (aliases?.length)
163
+ parts.push(`[ALIASES] ${aliases.join("; ")}`);
164
+ if (keywords?.length)
165
+ parts.push(`[KEYWORDS] ${keywords.join("; ")}`);
166
+ if (normalizedText)
167
+ parts.push(`[NORMALIZED] ${normalizedText}`);
168
+ if (rawText)
169
+ parts.push(`[RAW] ${rawText.slice(0, 400)}`);
170
+ return parts.join("\n");
171
+ }
172
+ // ============================================================
173
+ // 工具:解析 AI 返回的 JSON 数组
174
+ // ============================================================
175
+ /** 尝试从 LLM 响应中提取 CompiledChunk 数组 */
176
+ export function parseCompiledResult(text) {
177
+ try {
178
+ // 去除可能的 markdown 代码块包裹
179
+ let json = text.trim();
180
+ if (json.startsWith("```")) {
181
+ json = json.replace(/^```json?\s*\n?/, "").replace(/\n?```\s*$/, "");
182
+ }
183
+ const arr = JSON.parse(json);
184
+ if (!Array.isArray(arr))
185
+ return null;
186
+ // 基本校验
187
+ for (const item of arr) {
188
+ if (!item.key || !item.normalizedText)
189
+ return null;
190
+ }
191
+ return arr;
192
+ }
193
+ catch {
194
+ return null;
195
+ }
196
+ }
197
+ // ============================================================
198
+ // v5.2 文件级编译
199
+ // ============================================================
200
+ /** 文件级编译 System Prompt(只要求 LLM 做 4 件事) */
201
+ export const FILE_COMPILE_SYSTEM_PROMPT = `你是一个"知识语义编译器"。
202
+
203
+ 你的任务: 将整篇笔记转换为结构化的语义知识单元。
204
+
205
+ 你需要做的 4 件事:
206
+ 1. 自行判断语义边界 — 将文件分成若干连续的语义片段(segments)
207
+ 2. 为每个片段写出 topic(核心主题,一句话)
208
+ 3. 为每个片段写出 normalizedText(规范化文本:补全省略、统一术语、保留所有技术细节)
209
+ 4. 为每个片段提取 concepts(技术概念)和 aliases(同义表达,格式 "中文 ↔ English")
210
+
211
+ 核心原则:
212
+ - 保留原始信息 — 不删技术细节(API 名、参数、错误信息、缩写)
213
+ - 不改变原意 — 只规范化表达
214
+ - 语义边界 = 同一认知主题的自然段或连续段落
215
+ - 如果整个文件是单一主题,只输出 1 个 segment
216
+
217
+ 禁止: 过度总结、删除原文、改写逻辑、主观推断、引入不存在的信息。`;
218
+ /**
219
+ * 为文件级编译构建 prompt
220
+ * @param relPath 文件路径
221
+ * @param fullText 文件全文
222
+ * @param preprocessed 预处理器输出(仅展示给 LLM 参考)
223
+ */
224
+ export function buildFileCompilePrompt(relPath, fullText, preprocessed) {
225
+ const preSummary = preprocessed
226
+ .slice(0, 5)
227
+ .map((p) => ` - ${p.heading || "(无标题)"} [${p.chunkType}, ${p.contentClass}, imp=${p.importance.toFixed(1)}]`)
228
+ .join("\n");
229
+ return `请分析以下笔记文件。
230
+
231
+ 文件: ${relPath}
232
+ 程序预分析(仅供参考,你不需填写这些字段):
233
+ ${preSummary}
234
+
235
+ 你需要输出一个 JSON 对象:
236
+
237
+ {
238
+ "segments": [
239
+ {
240
+ "text": "片段原文(从文件中截取)",
241
+ "topic": "核心主题(一句话)",
242
+ "normalizedText": "规范化文本",
243
+ "concepts": ["技术概念"],
244
+ "aliases": ["同义表达 (格式: 中文 ↔ English)"]
245
+ }
246
+ ]
247
+ }
248
+
249
+ 注意事项:
250
+ - segments 按文件顺序排列
251
+ - 语义边界你自己判断: 同一认知主题归为一个 segment
252
+ - 一个 segment 可以包含多个自然段
253
+ - 至少输出 1 个 segment
254
+ - normalizedText 必须保留 ALL 技术细节
255
+ - 不要 markdown 代码块包裹,直接输出 JSON
256
+
257
+ === 文件全文 ===
258
+
259
+ ${fullText}`;
260
+ }
261
+ /** 从 LLM 响应中提取 FileSegment 数组 */
262
+ export function parseFileSegments(text) {
263
+ try {
264
+ let json = text.trim();
265
+ if (json.startsWith("```")) {
266
+ json = json.replace(/^```json?\s*\n?/, "").replace(/\n?```\s*$/, "");
267
+ }
268
+ const obj = JSON.parse(json);
269
+ const arr = obj.segments ?? obj;
270
+ if (!Array.isArray(arr))
271
+ return null;
272
+ for (const item of arr) {
273
+ if (!item.topic || !item.normalizedText)
274
+ return null;
275
+ }
276
+ return arr;
277
+ }
278
+ catch {
279
+ return null;
280
+ }
281
+ }
282
+ // ============================================================
283
+ // v5.4 文件级编译(简化版:不要求 segments,只要求 1 个文件的 4 字段)
284
+ // ============================================================
285
+ /** v5.4 文件级 System Prompt(极简版) */
286
+ export const FILE_LLM_SYSTEM_PROMPT = `你是一个"知识语义编译器"。
287
+
288
+ 你的任务: 将整篇笔记转换为结构化的语义元数据,用于增强语义搜索。
289
+
290
+ 你需要输出的 4 个字段:
291
+ 1. topic — 核心主题(一句话概括全文)
292
+ 2. normalizedText — 规范化文本(补全省略主语、统一术语、保留所有技术细节)
293
+ 3. concepts — 技术概念列表(3-8 个核心概念)
294
+ 4. aliases — 同义表达(格式 "中文 ↔ English",2-5 组)
295
+
296
+ 核心原则:
297
+ - 保留所有技术细节(API 名、参数、错误信息、缩写、版本号)
298
+ - 不改变原意,只规范化表达
299
+ - concepts 提取技术关键词,不是摘要
300
+ - aliases 覆盖中英对照和缩写展开
301
+
302
+ 禁止: 过度总结、删除原文、改写逻辑、主观推断、引入不存在的信息。`;
303
+ /**
304
+ * v5.4 构建简化文件级编译 prompt
305
+ */
306
+ export function buildFileLLMPrompt(relPath, fullText) {
307
+ return `请分析以下笔记文件,提取语义元数据。
308
+
309
+ 文件: ${relPath}
310
+
311
+ 输出一个 JSON 对象:
312
+
313
+ {
314
+ "topic": "核心主题(一句话)",
315
+ "normalizedText": "规范化文本",
316
+ "concepts": ["技术概念1", "技术概念2"],
317
+ "aliases": ["中文 ↔ English"]
318
+ }
319
+
320
+ 不要 markdown 代码块包裹,直接输出 JSON。
321
+
322
+ === 文件全文 ===
323
+
324
+ ${fullText}`;
325
+ }
326
+ /**
327
+ * v5.4 解析文件级 LLM 响应(单对象,非 segments 数组)
328
+ */
329
+ export function parseFileLLMResult(text) {
330
+ try {
331
+ let json = text.trim();
332
+ if (json.startsWith("```")) {
333
+ json = json.replace(/^```json?\s*\n?/, "").replace(/\n?```\s*$/, "");
334
+ }
335
+ const obj = JSON.parse(json);
336
+ // 兼容 v5.2 segments 格式 → 取第一个 segment
337
+ if (obj.segments && Array.isArray(obj.segments) && obj.segments.length > 0) {
338
+ const s = obj.segments[0];
339
+ return { topic: s.topic, normalizedText: s.normalizedText, concepts: s.concepts || [], aliases: s.aliases || [] };
340
+ }
341
+ // v5.4 新格式
342
+ if (obj.topic && obj.normalizedText) {
343
+ return {
344
+ topic: obj.topic,
345
+ normalizedText: obj.normalizedText,
346
+ concepts: obj.concepts || [],
347
+ aliases: obj.aliases || [],
348
+ };
349
+ }
350
+ return null;
351
+ }
352
+ catch {
353
+ return null;
354
+ }
355
+ }
356
+ /**
357
+ * v5.4 构建文件级 LLM 向量的 embedding 文本
358
+ */
359
+ export function buildFileLLMEmbeddingText(data, relPath, maxEmbedLen = 2000) {
360
+ const parts = [];
361
+ // 路径语义注入
362
+ if (relPath) {
363
+ const pathContext = relPath.replace(/\\/g, "/").replace(/\//g, " > ").replace(/\.md$/i, "");
364
+ parts.push(`[PATH] ${pathContext}`);
365
+ }
366
+ if (data.topic)
367
+ parts.push(`[TOPIC] ${data.topic}`);
368
+ if (data.concepts?.length)
369
+ parts.push(`[CONCEPTS] ${data.concepts.join("; ")}`);
370
+ if (data.aliases?.length)
371
+ parts.push(`[ALIASES] ${data.aliases.join("; ")}`);
372
+ if (data.normalizedText)
373
+ parts.push(`[NORMALIZED] ${data.normalizedText.slice(0, maxEmbedLen)}`);
374
+ return parts.join("\n");
375
+ }
376
+ //# sourceMappingURL=semantic-compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-compiler.js","sourceRoot":"","sources":["../src/semantic-compiler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { SearchHit } from "./types.js";
2
+ /** 纯语义搜索 */
3
+ export declare function semanticSearch(query: string): Promise<SearchHit[]>;
4
+ /** 混合搜索:关键词 + 语义并行 → RRF 融合排序
5
+ *
6
+ * RRF (Reciprocal Rank Fusion):
7
+ * RRF(d) = Σ 1/(k + rank_i(d))
8
+ * 各列表取 Top-N 参与融合,未出现在某列表中的项 rank = RRF_K*2
9
+ */
10
+ export declare function hybridSearch(query: string): Promise<SearchHit[]>;
11
+ //# sourceMappingURL=semantic-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-search.d.ts","sourceRoot":"","sources":["../src/semantic-search.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA0C5C,YAAY;AACZ,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CA6FxE;AA+CD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAkEtE"}
@@ -0,0 +1,217 @@
1
+ // semantic-search.ts — 语义搜索 & 混合搜索 (v5.1)
2
+ //
3
+ // semanticSearch: query → embed → 余弦相似度 → 同文件多块聚合加分
4
+ // hybridSearch: 关键词 + 语义并行 → RRF 融合排序 (k=60, Top-50)
5
+ //
6
+ // 策略:
7
+ // 高阈值 0.50 — 只有置信度 ≥50% 的语义匹配才视为有效
8
+ // 兜底 — 高阈值结果不足 3 条时,追加 ≤3 条低分结果(标记"弱匹配")
9
+ // 同文件合并 — 一个文件多个块命中时,取最高块相似度 + (块数-1)*0.05 加分(上限 0.25)
10
+ // RRF 融合 — 替代简单线性加权,对异构分数尺度不敏感
11
+ import { getEmbeddings, getSemanticEnabled, getChunkInfo } from "./store.js";
12
+ import { getIndex } from "./store.js";
13
+ import { embed, initialize, isAvailable, cosineSimilarity } from "./embedder.js";
14
+ import { keywordSearch } from "./search.js";
15
+ /** 高置信度阈值 — ≥50% 视为强匹配 */
16
+ const HIGH_SIMILARITY_THRESHOLD = 0.50;
17
+ /** 最低阈值 — 低于此值不展示(即使兜底) */
18
+ const MIN_SIMILARITY_THRESHOLD = 0.20;
19
+ /** 兜底条数 — 强匹配不足时最多追加几条弱匹配 */
20
+ const FALLBACK_COUNT = 3;
21
+ /** 多块加分:每额外一个命中块 +0.05,上限 0.25 */
22
+ const MULTI_CHUNK_BONUS = 0.05;
23
+ const MAX_MULTI_CHUNK_BONUS = 0.25;
24
+ /** RRF 融合常数 (标准值 60) */
25
+ const RRF_K = 60;
26
+ /** 各列表参与 RRF 融合的 Top-N 上限 */
27
+ const RRF_TOPN = 50;
28
+ /** 纯语义搜索 */
29
+ export async function semanticSearch(query) {
30
+ if (!getSemanticEnabled())
31
+ return [];
32
+ if (!isAvailable()) {
33
+ const ok = await initialize();
34
+ if (!ok)
35
+ return [];
36
+ }
37
+ const embeddings = getEmbeddings();
38
+ if (Object.keys(embeddings).length === 0)
39
+ return [];
40
+ const idx = getIndex();
41
+ const chunkInfo = getChunkInfo();
42
+ let queryVec;
43
+ try {
44
+ queryVec = await embed(query);
45
+ }
46
+ catch {
47
+ return [];
48
+ }
49
+ // 1. 计算所有块的相似度
50
+ const allChunks = [];
51
+ for (const [key, vec] of Object.entries(embeddings)) {
52
+ const chunkMatch = key.match(/^(.*)###(\d+|llm)$/);
53
+ const relPath = chunkMatch ? chunkMatch[1] : key;
54
+ const rawIdx = chunkMatch ? parseInt(chunkMatch[2], 10) : NaN;
55
+ const chunkIdx = isNaN(rawIdx) ? undefined : rawIdx;
56
+ if (!idx[relPath])
57
+ continue;
58
+ const similarity = cosineSimilarity(queryVec, vec);
59
+ if (similarity < MIN_SIMILARITY_THRESHOLD)
60
+ continue;
61
+ const ci = chunkIdx !== undefined ? chunkInfo[key] : undefined;
62
+ allChunks.push({
63
+ key,
64
+ relPath,
65
+ similarity,
66
+ chunkIndex: chunkIdx,
67
+ chunkHeading: ci ? ci.heading.replace(/^#+\s*/, "") : undefined,
68
+ });
69
+ }
70
+ // 2. 同文件聚合:取最高块 + 多块加分
71
+ const fileMap = new Map();
72
+ for (const ch of allChunks) {
73
+ const existing = fileMap.get(ch.relPath);
74
+ if (!existing) {
75
+ fileMap.set(ch.relPath, {
76
+ relPath: ch.relPath,
77
+ semanticScore: ch.similarity,
78
+ bestChunk: ch,
79
+ chunkCount: 1,
80
+ chunkHeadings: ch.chunkHeading ? [ch.chunkHeading] : [],
81
+ });
82
+ }
83
+ else {
84
+ // 追踪最高分块
85
+ if (ch.similarity > existing.bestChunk.similarity) {
86
+ existing.bestChunk = ch;
87
+ }
88
+ existing.chunkCount++;
89
+ if (ch.chunkHeading && !existing.chunkHeadings.includes(ch.chunkHeading)) {
90
+ existing.chunkHeadings.push(ch.chunkHeading);
91
+ }
92
+ }
93
+ }
94
+ // 计算最终分数:最高块相似度 + 多块加分
95
+ for (const fm of fileMap.values()) {
96
+ const bonus = Math.min((fm.chunkCount - 1) * MULTI_CHUNK_BONUS, MAX_MULTI_CHUNK_BONUS);
97
+ fm.semanticScore = fm.bestChunk.similarity + bonus;
98
+ }
99
+ const files = [...fileMap.values()].sort((a, b) => b.semanticScore - a.semanticScore);
100
+ // 3. 强匹配(聚合后 ≥50%)/ 弱匹配兜底
101
+ const strong = files.filter(f => f.semanticScore >= HIGH_SIMILARITY_THRESHOLD);
102
+ const ci = getChunkInfo();
103
+ const strongHits = strong.map(f => makeFileHit(f, idx, ci));
104
+ if (strongHits.length < FALLBACK_COUNT) {
105
+ const weak = files
106
+ .filter(f => f.semanticScore < HIGH_SIMILARITY_THRESHOLD)
107
+ .slice(0, FALLBACK_COUNT);
108
+ const weakHits = weak.map(f => {
109
+ const hit = makeFileHit(f, idx, ci);
110
+ hit.snippet = `⚠️ 弱匹配 (${Math.round(f.semanticScore * 100)}%)`;
111
+ return hit;
112
+ });
113
+ return [...strongHits, ...weakHits];
114
+ }
115
+ return strongHits;
116
+ }
117
+ function makeFileHit(f, idx, chunkInfo) {
118
+ const entry = idx[f.relPath];
119
+ // 优先展示 LLM 编译结果(summary / topic),其次 AST 块标题
120
+ let snippet = "";
121
+ const llmKey = `${f.relPath}###llm`;
122
+ const llm = chunkInfo?.[llmKey];
123
+ if (llm?.summary) {
124
+ snippet = `💡 ${llm.summary}`;
125
+ if (llm.topic)
126
+ snippet += ` [${llm.topic}]`;
127
+ }
128
+ else if (llm?.topic) {
129
+ snippet = `💡 ${llm.topic}`;
130
+ }
131
+ else if (f.bestChunk.chunkHeading) {
132
+ snippet = `▸ ${f.bestChunk.chunkHeading}`;
133
+ }
134
+ // 多块命中展示(最多 5 个附加标题)
135
+ if (f.chunkCount > 1) {
136
+ const others = f.chunkHeadings
137
+ .filter(h => h !== f.bestChunk.chunkHeading)
138
+ .slice(0, 5);
139
+ if (others.length > 0) {
140
+ snippet += ` | +${f.chunkCount - 1}块: ${others.join(", ")}`;
141
+ }
142
+ else {
143
+ snippet += ` | +${f.chunkCount - 1}块命中`;
144
+ }
145
+ }
146
+ return {
147
+ relPath: entry.relPath,
148
+ sourceDir: entry.sourceDir,
149
+ title: entry.title,
150
+ tags: entry.tags,
151
+ snippet,
152
+ score: Math.round(f.semanticScore * 100),
153
+ semanticScore: f.semanticScore,
154
+ chunkIndex: f.bestChunk.chunkIndex,
155
+ chunkHeading: f.bestChunk.chunkHeading,
156
+ };
157
+ }
158
+ /** 混合搜索:关键词 + 语义并行 → RRF 融合排序
159
+ *
160
+ * RRF (Reciprocal Rank Fusion):
161
+ * RRF(d) = Σ 1/(k + rank_i(d))
162
+ * 各列表取 Top-N 参与融合,未出现在某列表中的项 rank = RRF_K*2
163
+ */
164
+ export async function hybridSearch(query) {
165
+ const keywordHits = keywordSearch(query);
166
+ const semanticHits = await semanticSearch(query);
167
+ // 按分数排序并取 Top-N
168
+ const kwSorted = [...keywordHits]
169
+ .sort((a, b) => b.score - a.score)
170
+ .slice(0, RRF_TOPN);
171
+ const semSorted = [...semanticHits]
172
+ .sort((a, b) => b.score - a.score)
173
+ .slice(0, RRF_TOPN);
174
+ // 构建 rank 映射 (1-based)
175
+ const kwRank = new Map();
176
+ kwSorted.forEach((h, i) => kwRank.set(h.relPath, i + 1));
177
+ const semRank = new Map();
178
+ semSorted.forEach((h, i) => semRank.set(h.relPath, i + 1));
179
+ // 收集所有唯一文件
180
+ const allPaths = new Set([
181
+ ...kwSorted.map(h => h.relPath),
182
+ ...semSorted.map(h => h.relPath),
183
+ ]);
184
+ // 构建查找表
185
+ const kwMap = new Map(kwSorted.map(h => [h.relPath, h]));
186
+ const semMap = new Map(semSorted.map(h => [h.relPath, h]));
187
+ // RRF 缺省排名(未出现在某列表中的项用此值)
188
+ const missingRank = RRF_K * 2;
189
+ const merged = [];
190
+ for (const relPath of allPaths) {
191
+ const kw = kwMap.get(relPath);
192
+ const sem = semMap.get(relPath);
193
+ const kwR = kwRank.get(relPath) ?? missingRank;
194
+ const semR = semRank.get(relPath) ?? missingRank;
195
+ const rrf = 1 / (RRF_K + kwR) + 1 / (RRF_K + semR);
196
+ // 取最佳信息源构建结果
197
+ const base = sem || kw;
198
+ // 优先语义结果 snippet(含 LLM 编译内容),其次关键词 snippet
199
+ let snippet = sem?.snippet || "";
200
+ if (!snippet && kw?.snippet) {
201
+ snippet = kw.snippet.replace(/\n/g, " | ");
202
+ }
203
+ merged.push({
204
+ relPath: base.relPath,
205
+ sourceDir: base.sourceDir,
206
+ title: base.title,
207
+ tags: base.tags,
208
+ snippet,
209
+ score: Math.round(rrf * 10000),
210
+ semanticScore: sem?.semanticScore,
211
+ chunkIndex: sem?.chunkIndex,
212
+ chunkHeading: sem?.chunkHeading,
213
+ });
214
+ }
215
+ return merged.sort((a, b) => b.score - a.score);
216
+ }
217
+ //# sourceMappingURL=semantic-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-search.js","sourceRoot":"","sources":["../src/semantic-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { FileEntry } from "./types.js";
2
+ export declare function setWikiHome(path: string): void;
3
+ interface WikiSettings {
4
+ sources: string[];
5
+ index: Record<string, FileEntry>;
6
+ lastScan: string;
7
+ semanticEnabled?: boolean;
8
+ currentModelId?: string;
9
+ }
10
+ export declare function readAll(): WikiSettings;
11
+ export declare function writeAll(s: WikiSettings): void;
12
+ export declare function getSources(): string[];
13
+ export declare function addSource(absPath: string): boolean;
14
+ /** 移除数据源并清理关联索引和语义向量 */
15
+ export declare function removeSource(target: string): string | null;
16
+ export declare function getIndex(): Record<string, FileEntry>;
17
+ export declare function mergeIndex(entries: FileEntry[]): void;
18
+ export declare function removeEntry(relPath: string): boolean;
19
+ export declare function updateEntryPath(oldRelPath: string, newRelPath: string, entry: FileEntry): boolean;
20
+ export declare function getEntry(relPath: string): FileEntry | null;
21
+ export declare function getWikiModel(): string;
22
+ export declare function readModelId(): string | undefined;
23
+ export declare function writeModelId(id: string): void;
24
+ export declare function getSemanticEnabled(): boolean;
25
+ export declare function setSemanticEnabled(enabled: boolean): void;
26
+ export declare function sourcesStats(): {
27
+ sources: number;
28
+ files: number;
29
+ lastScan: string;
30
+ };
31
+ export {};
32
+ //# sourceMappingURL=store-settings.d.ts.map