@astro-minimax/ai 0.7.4 → 0.8.0
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/components/AIChatContainer.d.ts +9 -0
- package/dist/components/AIChatContainer.d.ts.map +1 -0
- package/dist/components/AIChatContainer.js +936 -0
- package/{src → dist}/components/AIChatWidget.astro +1 -1
- package/dist/components/ChatPanel.d.ts +19 -0
- package/dist/components/ChatPanel.d.ts.map +1 -0
- package/dist/components/ChatPanel.js +914 -0
- package/dist/data/index.js +18 -1
- package/dist/fact-registry/index.js +16 -3
- package/dist/index.js +11 -30
- package/dist/intelligence/evidence-analysis.d.ts.map +1 -1
- package/dist/intelligence/index.js +56 -5
- package/dist/intelligence/keyword-extract.d.ts.map +1 -1
- package/dist/middleware/index.js +10 -1
- package/dist/prompt/index.js +10 -4
- package/dist/provider-manager/base.d.ts +1 -0
- package/dist/provider-manager/base.d.ts.map +1 -1
- package/dist/provider-manager/types.d.ts +1 -0
- package/dist/provider-manager/types.d.ts.map +1 -1
- package/dist/providers/index.js +5 -1
- package/dist/search/index.js +48 -6
- package/dist/server/dev-server.js +236 -259
- package/dist/server/index.js +39 -6
- package/dist/stream/index.js +8 -2
- package/package.json +16 -10
- package/dist/cache/global-cache.js +0 -141
- package/dist/cache/index.js +0 -62
- package/dist/cache/kv-adapter.js +0 -102
- package/dist/cache/memory-adapter.js +0 -95
- package/dist/cache/response-cache.js +0 -85
- package/dist/cache/types.js +0 -16
- package/dist/data/metadata-loader.js +0 -66
- package/dist/data/types.js +0 -1
- package/dist/fact-registry/fact-matcher.js +0 -94
- package/dist/fact-registry/prompt-injector.js +0 -57
- package/dist/fact-registry/registry.js +0 -38
- package/dist/fact-registry/types.js +0 -5
- package/dist/intelligence/citation-appender.js +0 -65
- package/dist/intelligence/citation-guard.js +0 -125
- package/dist/intelligence/evidence-analysis.js +0 -88
- package/dist/intelligence/intent-detect.js +0 -131
- package/dist/intelligence/keyword-extract.js +0 -114
- package/dist/intelligence/response-templates.js +0 -116
- package/dist/intelligence/types.js +0 -1
- package/dist/middleware/rate-limiter.js +0 -129
- package/dist/prompt/dynamic-layer.js +0 -67
- package/dist/prompt/prompt-builder.js +0 -12
- package/dist/prompt/semi-static-layer.js +0 -29
- package/dist/prompt/static-layer.js +0 -150
- package/dist/prompt/types.js +0 -1
- package/dist/provider-manager/base.js +0 -47
- package/dist/provider-manager/config.js +0 -134
- package/dist/provider-manager/index.js +0 -6
- package/dist/provider-manager/manager.js +0 -121
- package/dist/provider-manager/mock.js +0 -56
- package/dist/provider-manager/openai.js +0 -112
- package/dist/provider-manager/types.js +0 -6
- package/dist/provider-manager/workers.js +0 -74
- package/dist/providers/mock.js +0 -234
- package/dist/search/idf.js +0 -31
- package/dist/search/search-api.js +0 -119
- package/dist/search/search-index.js +0 -35
- package/dist/search/search-utils.js +0 -122
- package/dist/search/session-cache.js +0 -92
- package/dist/search/types.js +0 -1
- package/dist/search/vector-reranker.js +0 -135
- package/dist/server/chat-handler.js +0 -590
- package/dist/server/errors.js +0 -41
- package/dist/server/metadata-init.js +0 -47
- package/dist/server/notify.js +0 -74
- package/dist/server/stream-helpers.js +0 -197
- package/dist/server/types.js +0 -13
- package/dist/stream/mock-stream.js +0 -27
- package/dist/stream/response.js +0 -22
- package/dist/utils/i18n.js +0 -164
- package/src/components/AIChatContainer.tsx +0 -31
- package/src/components/ChatPanel.tsx +0 -866
- package/src/providers/mock.ts +0 -240
- package/src/server/types.ts +0 -89
- package/src/utils/i18n.ts +0 -238
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Optional TF-IDF vector reranker.
|
|
3
|
-
*
|
|
4
|
-
* When a pre-built vector index is available (from `vectorize.ts`),
|
|
5
|
-
* uses cosine similarity to refine the ranking of search results.
|
|
6
|
-
* Gracefully degrades to a no-op when no vector index is loaded.
|
|
7
|
-
*/
|
|
8
|
-
// ── State ────────────────────────────────────────────────────
|
|
9
|
-
let loadedIndex = null;
|
|
10
|
-
let idfCache = null;
|
|
11
|
-
export function loadVectorIndex(data) {
|
|
12
|
-
loadedIndex = data;
|
|
13
|
-
idfCache = null;
|
|
14
|
-
if (data?.vocabulary && data.chunks.length > 0) {
|
|
15
|
-
idfCache = buildIDFFromVocab(data.vocabulary, data.chunks);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
export function clearVectorIndex() {
|
|
19
|
-
loadedIndex = null;
|
|
20
|
-
idfCache = null;
|
|
21
|
-
}
|
|
22
|
-
export function hasVectorIndex() {
|
|
23
|
-
return loadedIndex !== null && loadedIndex.chunks.length > 0;
|
|
24
|
-
}
|
|
25
|
-
// ── Core: Rerank ──────────────────────────────────────────────
|
|
26
|
-
/**
|
|
27
|
-
* Reranks article search results using vector cosine similarity.
|
|
28
|
-
*
|
|
29
|
-
* For each candidate article, finds the best-matching chunk in the vector
|
|
30
|
-
* index and uses the cosine similarity as a reranking signal.
|
|
31
|
-
*
|
|
32
|
-
* Final score = original_score * (1 - alpha) + vector_score * alpha
|
|
33
|
-
*
|
|
34
|
-
* @param alpha - Blend factor (0 = ignore vectors, 1 = vectors only). Default 0.3
|
|
35
|
-
*/
|
|
36
|
-
export function rerankWithVectors(query, candidates, alpha = 0.3) {
|
|
37
|
-
if (!loadedIndex || !idfCache || !loadedIndex.vocabulary) {
|
|
38
|
-
return candidates;
|
|
39
|
-
}
|
|
40
|
-
const queryVector = computeQueryVector(query, loadedIndex.vocabulary, idfCache);
|
|
41
|
-
if (!queryVector)
|
|
42
|
-
return candidates;
|
|
43
|
-
// Map postId → best chunk cosine similarity
|
|
44
|
-
const articleScores = new Map();
|
|
45
|
-
for (const chunk of loadedIndex.chunks) {
|
|
46
|
-
if (!chunk.vector)
|
|
47
|
-
continue;
|
|
48
|
-
const sim = cosineSimilarity(queryVector, chunk.vector);
|
|
49
|
-
const current = articleScores.get(chunk.postId) ?? 0;
|
|
50
|
-
if (sim > current) {
|
|
51
|
-
articleScores.set(chunk.postId, sim);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (articleScores.size === 0)
|
|
55
|
-
return candidates;
|
|
56
|
-
// Normalize original scores to 0-1
|
|
57
|
-
const maxOriginal = Math.max(...candidates.map(c => c.score ?? 0), 1);
|
|
58
|
-
const reranked = candidates.map(article => {
|
|
59
|
-
const slug = extractSlugFromUrl(article.url);
|
|
60
|
-
const vectorScore = articleScores.get(slug) ?? 0;
|
|
61
|
-
const originalNorm = (article.score ?? 0) / maxOriginal;
|
|
62
|
-
const blended = originalNorm * (1 - alpha) + vectorScore * alpha;
|
|
63
|
-
return { ...article, score: blended };
|
|
64
|
-
});
|
|
65
|
-
return reranked.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
|
66
|
-
}
|
|
67
|
-
// ── Math Utilities ────────────────────────────────────────────
|
|
68
|
-
function cosineSimilarity(a, b) {
|
|
69
|
-
if (a.length !== b.length)
|
|
70
|
-
return 0;
|
|
71
|
-
let dot = 0, magA = 0, magB = 0;
|
|
72
|
-
for (let i = 0; i < a.length; i++) {
|
|
73
|
-
dot += a[i] * b[i];
|
|
74
|
-
magA += a[i] * a[i];
|
|
75
|
-
magB += b[i] * b[i];
|
|
76
|
-
}
|
|
77
|
-
const mag = Math.sqrt(magA) * Math.sqrt(magB);
|
|
78
|
-
return mag === 0 ? 0 : dot / mag;
|
|
79
|
-
}
|
|
80
|
-
function computeQueryVector(query, vocabulary, idf) {
|
|
81
|
-
const tokens = tokenizeForVector(query);
|
|
82
|
-
if (!tokens.length)
|
|
83
|
-
return null;
|
|
84
|
-
const tf = new Map();
|
|
85
|
-
for (const t of tokens)
|
|
86
|
-
tf.set(t, (tf.get(t) || 0) + 1);
|
|
87
|
-
const maxTf = Math.max(...tf.values(), 1);
|
|
88
|
-
const vector = vocabulary.map(term => {
|
|
89
|
-
const termTf = (tf.get(term) || 0) / maxTf;
|
|
90
|
-
const termIdf = idf.get(term) || 0;
|
|
91
|
-
return termTf * termIdf;
|
|
92
|
-
});
|
|
93
|
-
// Check if vector is all zeros
|
|
94
|
-
if (vector.every(v => v === 0))
|
|
95
|
-
return null;
|
|
96
|
-
return vector;
|
|
97
|
-
}
|
|
98
|
-
function tokenizeForVector(text) {
|
|
99
|
-
const CJK = /[\u4e00-\u9fff\u3400-\u4dbf]/g;
|
|
100
|
-
const cjkChars = text.match(CJK) || [];
|
|
101
|
-
const latin = text
|
|
102
|
-
.replace(CJK, ' ')
|
|
103
|
-
.toLowerCase()
|
|
104
|
-
.split(/\W+/)
|
|
105
|
-
.filter(w => w.length > 2);
|
|
106
|
-
return [...cjkChars, ...latin];
|
|
107
|
-
}
|
|
108
|
-
function buildIDFFromVocab(vocabulary, chunks) {
|
|
109
|
-
const N = chunks.length;
|
|
110
|
-
const df = new Map();
|
|
111
|
-
for (const chunk of chunks) {
|
|
112
|
-
const tokens = new Set(tokenizeForVector(chunk.text));
|
|
113
|
-
for (const term of vocabulary) {
|
|
114
|
-
if (tokens.has(term)) {
|
|
115
|
-
df.set(term, (df.get(term) || 0) + 1);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
const idf = new Map();
|
|
120
|
-
for (const term of vocabulary) {
|
|
121
|
-
const docCount = df.get(term) || 0;
|
|
122
|
-
idf.set(term, Math.log(N / (docCount + 1)) + 1);
|
|
123
|
-
}
|
|
124
|
-
return idf;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Extracts a slug/postId from a URL path like "/zh/posts/some-slug/" → "zh/some-slug"
|
|
128
|
-
*/
|
|
129
|
-
function extractSlugFromUrl(url) {
|
|
130
|
-
const path = url.replace(/^https?:\/\/[^/]+/, '');
|
|
131
|
-
const match = path.match(/^\/([\w-]+)\/posts\/(.+?)\/?$/);
|
|
132
|
-
if (match)
|
|
133
|
-
return `${match[1]}/${match[2]}`;
|
|
134
|
-
return path.replace(/^\/|\/$/g, '');
|
|
135
|
-
}
|