Skip to content

Commit 0beb258

Browse files
author
linyuan.yang
committed
searcher
1 parent 4c12791 commit 0beb258

1 file changed

Lines changed: 34 additions & 13 deletions

File tree

packages/scorpio.ai/src/Retrieval/HybridSearcher.ts

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,10 @@ export class HybridSearcher {
9797

9898
let totalLength = 0;
9999
for (const { key, text } of items) {
100-
const tokens = text.toLowerCase().split(/\s+/).filter(Boolean);
101-
this.docLengths.set(key, tokens.length);
102-
totalLength += tokens.length;
103-
104-
const termFreq = new Map<string, number>();
105-
for (const t of tokens) {
106-
termFreq.set(t, (termFreq.get(t) ?? 0) + 1);
107-
}
100+
const termFreq = tokenizeWithFreq(text);
101+
const docLen = [...termFreq.values()].reduce((a, b) => a + b, 0);
102+
this.docLengths.set(key, docLen);
103+
totalLength += docLen;
108104

109105
for (const [term, freq] of termFreq) {
110106
if (!this.invertedIndex.has(term)) {
@@ -134,13 +130,12 @@ export class HybridSearcher {
134130

135131
private updateInvertedEntry(key: string, text: string): void {
136132
this.removeInvertedEntry(key);
137-
const tokens = text.toLowerCase().split(/\s+/).filter(Boolean);
138-
this.docLengths.set(key, tokens.length);
133+
const termFreq = tokenizeWithFreq(text);
134+
const docLen = [...termFreq.values()].reduce((a, b) => a + b, 0);
135+
this.docLengths.set(key, docLen);
139136
this.totalDocs = this.docLengths.size;
140137
this.avgDocLength = [...this.docLengths.values()].reduce((a, b) => a + b, 0) / (this.totalDocs || 1);
141138

142-
const termFreq = new Map<string, number>();
143-
for (const t of tokens) termFreq.set(t, (termFreq.get(t) ?? 0) + 1);
144139
for (const [term, freq] of termFreq) {
145140
if (!this.invertedIndex.has(term)) this.invertedIndex.set(term, new Map());
146141
this.invertedIndex.get(term)!.set(key, freq);
@@ -225,8 +220,34 @@ export class HybridSearcher {
225220
}
226221
}
227222

223+
const STOP_WORDS = new Set([
224+
'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个',
225+
'上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好',
226+
'这', '那', '他', '她', '它', '们', '被', '把', '从', '对', '与', '为', '能',
227+
'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
228+
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should',
229+
'it', 'this', 'that', 'and', 'but', 'or', 'if', 'so',
230+
'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'as',
231+
]);
232+
233+
const segmenter = new Intl.Segmenter('zh-CN', { granularity: 'word' });
234+
228235
function tokenize(text: string): Set<string> {
229-
return new Set(text.toLowerCase().split(/\s+/).filter(Boolean));
236+
const tokens = new Set<string>();
237+
for (const { segment, isWordLike } of segmenter.segment(text.toLowerCase())) {
238+
if (isWordLike && !STOP_WORDS.has(segment)) tokens.add(segment);
239+
}
240+
return tokens;
241+
}
242+
243+
function tokenizeWithFreq(text: string): Map<string, number> {
244+
const freq = new Map<string, number>();
245+
for (const { segment, isWordLike } of segmenter.segment(text.toLowerCase())) {
246+
if (isWordLike && !STOP_WORDS.has(segment)) {
247+
freq.set(segment, (freq.get(segment) ?? 0) + 1);
248+
}
249+
}
250+
return freq;
230251
}
231252

232253
function calcBM25Score(

0 commit comments

Comments
 (0)