@astro-minimax/cli 0.5.0 → 0.7.1
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/README.md +69 -0
- package/dist/commands/ai.d.ts +2 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +99 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/data.d.ts +2 -0
- package/dist/commands/data.d.ts.map +1 -0
- package/dist/commands/data.js +111 -0
- package/dist/commands/data.js.map +1 -0
- package/dist/commands/hooks.d.ts +2 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +378 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +50 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/podcast.d.ts +2 -0
- package/dist/commands/podcast.d.ts.map +1 -0
- package/dist/commands/podcast.js +89 -0
- package/dist/commands/podcast.js.map +1 -0
- package/dist/commands/post.d.ts +2 -0
- package/dist/commands/post.d.ts.map +1 -0
- package/dist/commands/post.js +190 -0
- package/dist/commands/post.js.map +1 -0
- package/dist/commands/profile.d.ts +2 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +88 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +81 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/ai-process.d.ts +20 -0
- package/dist/tools/ai-process.d.ts.map +1 -0
- package/dist/tools/ai-process.js +607 -0
- package/dist/tools/ai-process.js.map +1 -0
- package/dist/tools/build-author-context.d.ts +13 -0
- package/dist/tools/build-author-context.d.ts.map +1 -0
- package/dist/tools/build-author-context.js +313 -0
- package/dist/tools/build-author-context.js.map +1 -0
- package/dist/tools/build-voice-profile.d.ts +12 -0
- package/dist/tools/build-voice-profile.d.ts.map +1 -0
- package/dist/tools/build-voice-profile.js +270 -0
- package/dist/tools/build-voice-profile.js.map +1 -0
- package/dist/tools/eval-ai-chat.d.ts +17 -0
- package/dist/tools/eval-ai-chat.d.ts.map +1 -0
- package/dist/tools/eval-ai-chat.js +362 -0
- package/dist/tools/eval-ai-chat.js.map +1 -0
- package/dist/tools/generate-author-profile.d.ts +14 -0
- package/dist/tools/generate-author-profile.d.ts.map +1 -0
- package/dist/tools/generate-author-profile.js +289 -0
- package/dist/tools/generate-author-profile.js.map +1 -0
- package/dist/tools/generate-cover.d.ts +14 -0
- package/dist/tools/generate-cover.d.ts.map +1 -0
- package/dist/tools/generate-cover.js +95 -0
- package/dist/tools/generate-cover.js.map +1 -0
- package/dist/tools/generate-og.d.ts +3 -0
- package/dist/tools/generate-og.d.ts.map +1 -0
- package/dist/tools/generate-og.js +254 -0
- package/dist/tools/generate-og.js.map +1 -0
- package/dist/tools/generate-related.d.ts +11 -0
- package/dist/tools/generate-related.d.ts.map +1 -0
- package/dist/tools/generate-related.js +124 -0
- package/dist/tools/generate-related.js.map +1 -0
- package/dist/tools/generate-tags.d.ts +14 -0
- package/dist/tools/generate-tags.d.ts.map +1 -0
- package/dist/tools/generate-tags.js +182 -0
- package/dist/tools/generate-tags.js.map +1 -0
- package/dist/tools/lib/ai-provider.d.ts +43 -0
- package/dist/tools/lib/ai-provider.d.ts.map +1 -0
- package/dist/tools/lib/ai-provider.js +146 -0
- package/dist/tools/lib/ai-provider.js.map +1 -0
- package/dist/tools/lib/audio-processor.d.ts +46 -0
- package/dist/tools/lib/audio-processor.d.ts.map +1 -0
- package/dist/tools/lib/audio-processor.js +188 -0
- package/dist/tools/lib/audio-processor.js.map +1 -0
- package/dist/tools/lib/frontmatter.d.ts +11 -0
- package/dist/tools/lib/frontmatter.d.ts.map +1 -0
- package/dist/tools/lib/frontmatter.js +80 -0
- package/dist/tools/lib/frontmatter.js.map +1 -0
- package/dist/tools/lib/index.d.ts +7 -0
- package/dist/tools/lib/index.d.ts.map +1 -0
- package/{template/tools/lib/index.ts → dist/tools/lib/index.js} +1 -0
- package/dist/tools/lib/index.js.map +1 -0
- package/dist/tools/lib/markdown.d.ts +6 -0
- package/dist/tools/lib/markdown.d.ts.map +1 -0
- package/dist/tools/lib/markdown.js +34 -0
- package/dist/tools/lib/markdown.js.map +1 -0
- package/dist/tools/lib/posts.d.ts +25 -0
- package/dist/tools/lib/posts.d.ts.map +1 -0
- package/dist/tools/lib/posts.js +63 -0
- package/dist/tools/lib/posts.js.map +1 -0
- package/dist/tools/lib/script-generator.d.ts +61 -0
- package/dist/tools/lib/script-generator.d.ts.map +1 -0
- package/dist/tools/lib/script-generator.js +182 -0
- package/dist/tools/lib/script-generator.js.map +1 -0
- package/dist/tools/lib/tts-provider.d.ts +65 -0
- package/dist/tools/lib/tts-provider.d.ts.map +1 -0
- package/dist/tools/lib/tts-provider.js +116 -0
- package/dist/tools/lib/tts-provider.js.map +1 -0
- package/dist/tools/lib/types.d.ts +129 -0
- package/dist/tools/lib/types.d.ts.map +1 -0
- package/dist/tools/lib/types.js +64 -0
- package/dist/tools/lib/types.js.map +1 -0
- package/dist/tools/lib/utils.d.ts +18 -0
- package/dist/tools/lib/utils.d.ts.map +1 -0
- package/dist/tools/lib/utils.js +121 -0
- package/dist/tools/lib/utils.js.map +1 -0
- package/dist/tools/lib/vectors.d.ts +27 -0
- package/dist/tools/lib/vectors.d.ts.map +1 -0
- package/dist/tools/lib/vectors.js +64 -0
- package/dist/tools/lib/vectors.js.map +1 -0
- package/dist/tools/podcast-feed.d.ts +6 -0
- package/dist/tools/podcast-feed.d.ts.map +1 -0
- package/dist/tools/podcast-feed.js +121 -0
- package/dist/tools/podcast-feed.js.map +1 -0
- package/dist/tools/podcast-generate.d.ts +15 -0
- package/dist/tools/podcast-generate.d.ts.map +1 -0
- package/dist/tools/podcast-generate.js +318 -0
- package/dist/tools/podcast-generate.js.map +1 -0
- package/dist/tools/podcast-list.d.ts +6 -0
- package/dist/tools/podcast-list.d.ts.map +1 -0
- package/dist/tools/podcast-list.js +66 -0
- package/dist/tools/podcast-list.js.map +1 -0
- package/dist/tools/summarize.d.ts +16 -0
- package/dist/tools/summarize.d.ts.map +1 -0
- package/dist/tools/summarize.js +108 -0
- package/dist/tools/summarize.js.map +1 -0
- package/dist/tools/translate.d.ts +13 -0
- package/dist/tools/translate.d.ts.map +1 -0
- package/dist/tools/translate.js +46 -0
- package/dist/tools/translate.js.map +1 -0
- package/dist/tools/vectorize.d.ts +13 -0
- package/dist/tools/vectorize.d.ts.map +1 -0
- package/dist/tools/vectorize.js +87 -0
- package/dist/tools/vectorize.js.map +1 -0
- package/package.json +14 -9
- package/template/astro.config.ts +8 -28
- package/template/datas/ai-seo.json +8 -0
- package/template/datas/ai-skip-list.json +1 -0
- package/template/datas/author-profile-context.json +21 -0
- package/template/datas/author-profile-report.json +21 -0
- package/template/datas/eval/gold-set.json +72 -0
- package/template/functions/README.md +82 -0
- package/template/functions/api/ai-info.ts +2 -2
- package/template/functions/api/chat.ts +4 -1
- package/template/functions/api/notify/comment.ts +140 -68
- package/template/functions/api/notify/debug.ts +41 -0
- package/template/functions/api/notify/status.ts +97 -0
- package/template/functions/api/notify/test-ai-chat.ts +67 -0
- package/template/package.json +22 -25
- package/template/src/config.ts +11 -0
- package/template/src/content.config.ts +29 -16
- package/template/src/env.d.ts +0 -5
- package/index.js +0 -36
- package/template/tools/README.md +0 -169
- package/template/tools/ai-process.ts +0 -816
- package/template/tools/build-author-context.ts +0 -405
- package/template/tools/build-voice-profile.ts +0 -322
- package/template/tools/generate-author-profile.ts +0 -369
- package/template/tools/generate-cover.ts +0 -123
- package/template/tools/generate-og.ts +0 -280
- package/template/tools/generate-related.ts +0 -146
- package/template/tools/generate-tags.ts +0 -251
- package/template/tools/lib/ai-provider.ts +0 -240
- package/template/tools/lib/frontmatter.ts +0 -94
- package/template/tools/lib/markdown.ts +0 -40
- package/template/tools/lib/posts.ts +0 -89
- package/template/tools/lib/utils.ts +0 -138
- package/template/tools/lib/vectors.ts +0 -96
- package/template/tools/summarize.ts +0 -142
- package/template/tools/translate.ts +0 -60
- package/template/tools/vectorize.ts +0 -105
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* 博客内容向量化与索引生成
|
|
4
|
+
*
|
|
5
|
+
* 用法:
|
|
6
|
+
* pnpm run tools:vectorize # TF-IDF 模式(无需 API Key)
|
|
7
|
+
* pnpm run tools:vectorize --openai # OpenAI Embeddings 模式
|
|
8
|
+
*
|
|
9
|
+
* 环境变量:
|
|
10
|
+
* AI_API_KEY / OPENAI_API_KEY(仅 --openai 模式需要)
|
|
11
|
+
*/
|
|
12
|
+
import { writeFile, mkdir } from "node:fs/promises";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { chunkText } from "./lib/markdown.js";
|
|
15
|
+
import { getAllPosts } from "./lib/posts.js";
|
|
16
|
+
import { generateEmbeddings } from "./lib/ai-provider.js";
|
|
17
|
+
import { generateTfIdfVectors, } from "./lib/vectors.js";
|
|
18
|
+
const OUTPUT_DIR = join(process.cwd(), "src/data/vectors");
|
|
19
|
+
const OUTPUT_FILE = join(OUTPUT_DIR, "index.json");
|
|
20
|
+
const CHUNK_SIZE = 500;
|
|
21
|
+
const CHUNK_OVERLAP = 50;
|
|
22
|
+
async function main() {
|
|
23
|
+
const useOpenAI = process.argv.includes("--openai");
|
|
24
|
+
const method = useOpenAI ? "openai" : "tfidf";
|
|
25
|
+
console.log(`📚 读取博客文章...`);
|
|
26
|
+
const posts = await getAllPosts();
|
|
27
|
+
console.log(` 找到 ${posts.length} 篇文章\n`);
|
|
28
|
+
console.log(`📝 分割内容块...`);
|
|
29
|
+
const chunks = [];
|
|
30
|
+
for (const post of posts) {
|
|
31
|
+
const fullText = `${post.title}\n${post.description}\n${post.body}`;
|
|
32
|
+
const textChunks = chunkText(fullText, CHUNK_SIZE, CHUNK_OVERLAP);
|
|
33
|
+
for (let i = 0; i < textChunks.length; i++) {
|
|
34
|
+
chunks.push({
|
|
35
|
+
postId: post.id,
|
|
36
|
+
title: post.title,
|
|
37
|
+
lang: post.lang,
|
|
38
|
+
chunkIndex: i,
|
|
39
|
+
text: textChunks[i],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
console.log(` 生成 ${chunks.length} 个内容块\n`);
|
|
44
|
+
if (method === "openai") {
|
|
45
|
+
console.log(`🧠 使用 OpenAI Embeddings 生成向量...`);
|
|
46
|
+
const texts = chunks.map(c => c.text);
|
|
47
|
+
const vectors = await generateEmbeddings(texts);
|
|
48
|
+
chunks.forEach((c, i) => {
|
|
49
|
+
c.vector = vectors[i];
|
|
50
|
+
});
|
|
51
|
+
const index = {
|
|
52
|
+
version: 1,
|
|
53
|
+
method: "openai",
|
|
54
|
+
createdAt: new Date().toISOString(),
|
|
55
|
+
chunks,
|
|
56
|
+
};
|
|
57
|
+
await mkdir(OUTPUT_DIR, { recursive: true });
|
|
58
|
+
await writeFile(OUTPUT_FILE, JSON.stringify(index, null, 0), "utf-8");
|
|
59
|
+
const fileSize = (JSON.stringify(index).length / 1024).toFixed(1);
|
|
60
|
+
console.log(`\n✅ 索引已生成: ${OUTPUT_FILE}`);
|
|
61
|
+
console.log(` 文件大小: ${fileSize} KB`);
|
|
62
|
+
console.log(` 内容块: ${chunks.length}`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(`🔢 使用 TF-IDF 生成向量...`);
|
|
66
|
+
const { vocabulary, vectors } = generateTfIdfVectors(chunks);
|
|
67
|
+
chunks.forEach((c, i) => {
|
|
68
|
+
c.vector = vectors[i];
|
|
69
|
+
});
|
|
70
|
+
const index = {
|
|
71
|
+
version: 1,
|
|
72
|
+
method: "tfidf",
|
|
73
|
+
createdAt: new Date().toISOString(),
|
|
74
|
+
vocabulary,
|
|
75
|
+
chunks,
|
|
76
|
+
};
|
|
77
|
+
await mkdir(OUTPUT_DIR, { recursive: true });
|
|
78
|
+
await writeFile(OUTPUT_FILE, JSON.stringify(index, null, 0), "utf-8");
|
|
79
|
+
const fileSize = (JSON.stringify(index).length / 1024).toFixed(1);
|
|
80
|
+
console.log(`\n✅ 索引已生成: ${OUTPUT_FILE}`);
|
|
81
|
+
console.log(` 文件大小: ${fileSize} KB`);
|
|
82
|
+
console.log(` 词汇量: ${vocabulary.length}`);
|
|
83
|
+
console.log(` 内容块: ${chunks.length}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
main().catch(console.error);
|
|
87
|
+
//# sourceMappingURL=vectorize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vectorize.js","sourceRoot":"","sources":["../../src/tools/vectorize.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astro-minimax/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "CLI tool
|
|
5
|
+
"description": "CLI tool for astro-minimax blog — create blogs, manage content, and process data with AI.",
|
|
6
6
|
"author": "Souloss",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"astro",
|
|
10
|
-
"scaffold",
|
|
11
10
|
"cli",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
11
|
+
"blog",
|
|
12
|
+
"scaffold",
|
|
13
|
+
"ai"
|
|
15
14
|
],
|
|
16
15
|
"homepage": "https://github.com/souloss/astro-minimax#readme",
|
|
17
16
|
"bugs": {
|
|
@@ -23,14 +22,18 @@
|
|
|
23
22
|
"directory": "packages/cli"
|
|
24
23
|
},
|
|
25
24
|
"bin": {
|
|
26
|
-
"astro-minimax": "./index.js"
|
|
25
|
+
"astro-minimax": "./dist/index.js"
|
|
27
26
|
},
|
|
28
27
|
"files": [
|
|
29
|
-
"
|
|
28
|
+
"dist/",
|
|
30
29
|
"template/"
|
|
31
30
|
],
|
|
32
|
-
"
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"tsx": "^4.21.0",
|
|
33
|
+
"undici": "^7.24.1"
|
|
34
|
+
},
|
|
33
35
|
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.0.0",
|
|
34
37
|
"astro": "^5.0.0",
|
|
35
38
|
"typescript": "^5.9.3"
|
|
36
39
|
},
|
|
@@ -39,6 +42,8 @@
|
|
|
39
42
|
"pnpm": ">=9.0.0"
|
|
40
43
|
},
|
|
41
44
|
"scripts": {
|
|
45
|
+
"build": "tsc",
|
|
46
|
+
"dev": "tsc --watch",
|
|
42
47
|
"typecheck": "tsc --noEmit"
|
|
43
48
|
}
|
|
44
49
|
}
|
package/template/astro.config.ts
CHANGED
|
@@ -5,8 +5,7 @@ import minimaxViz from "@astro-minimax/viz";
|
|
|
5
5
|
import sitemap from "@astrojs/sitemap";
|
|
6
6
|
import mdx from "@astrojs/mdx";
|
|
7
7
|
import preact from "@astrojs/preact";
|
|
8
|
-
|
|
9
|
-
import remarkCollapse from "remark-collapse";
|
|
8
|
+
|
|
10
9
|
import remarkMath from "remark-math";
|
|
11
10
|
import remarkGithubAlerts from "remark-github-alerts";
|
|
12
11
|
import remarkEmoji from "remark-emoji";
|
|
@@ -32,7 +31,8 @@ import { SITE } from "./src/config";
|
|
|
32
31
|
import { SOCIALS, SHARE_LINKS } from "./src/constants";
|
|
33
32
|
import { FRIENDS } from "./src/data/friends";
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
+
const asTransformer = (t: any) => t;
|
|
36
36
|
|
|
37
37
|
const shikiTransformers = [
|
|
38
38
|
asTransformer(updateStyle()),
|
|
@@ -76,13 +76,12 @@ export default defineConfig({
|
|
|
76
76
|
],
|
|
77
77
|
markdown: {
|
|
78
78
|
remarkPlugins: [
|
|
79
|
-
remarkToc,
|
|
80
|
-
[remarkCollapse, { test: "Table of contents" }],
|
|
81
79
|
remarkMath,
|
|
82
80
|
remarkGithubAlerts,
|
|
83
81
|
remarkEmoji,
|
|
84
82
|
remarkReadingTime,
|
|
85
|
-
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
[remarkAddZoomable as any, { className: "zoomable" }],
|
|
86
85
|
],
|
|
87
86
|
rehypePlugins: [
|
|
88
87
|
rehypeKatex,
|
|
@@ -98,28 +97,10 @@ export default defineConfig({
|
|
|
98
97
|
},
|
|
99
98
|
},
|
|
100
99
|
vite: {
|
|
101
|
-
plugins: [
|
|
102
|
-
tailwindcss() as never,
|
|
103
|
-
{
|
|
104
|
-
name: "astro-minimax-preact-singleton",
|
|
105
|
-
enforce: "pre" as const,
|
|
106
|
-
async resolveId(source, importer, options) {
|
|
107
|
-
if (source.startsWith("@/components/media")) {
|
|
108
|
-
const vizDir = new URL("../../packages/viz/src/components", import.meta.url).pathname;
|
|
109
|
-
return this.resolve(source.replace("@/components/media", vizDir), importer, { ...options, skipSelf: true });
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
],
|
|
100
|
+
plugins: [tailwindcss() as never],
|
|
114
101
|
server: {
|
|
115
102
|
fs: {
|
|
116
|
-
strict:
|
|
117
|
-
allow: [
|
|
118
|
-
new URL("../../packages", import.meta.url).pathname,
|
|
119
|
-
new URL("../../node_modules", import.meta.url).pathname,
|
|
120
|
-
"./src",
|
|
121
|
-
"./.astro",
|
|
122
|
-
],
|
|
103
|
+
strict: false,
|
|
123
104
|
},
|
|
124
105
|
proxy: {
|
|
125
106
|
"/api": {
|
|
@@ -130,8 +111,7 @@ export default defineConfig({
|
|
|
130
111
|
},
|
|
131
112
|
resolve: {
|
|
132
113
|
alias: {
|
|
133
|
-
"@/
|
|
134
|
-
"@/" : new URL("./src/", import.meta.url).pathname,
|
|
114
|
+
"@/": new URL("./src/", import.meta.url).pathname,
|
|
135
115
|
"react": "preact/compat",
|
|
136
116
|
"react-dom": "preact/compat",
|
|
137
117
|
"react/jsx-runtime": "preact/jsx-runtime",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generatedAt": null,
|
|
3
|
+
"siteUrl": null,
|
|
4
|
+
"sourceInfo": {
|
|
5
|
+
"totalPosts": 0,
|
|
6
|
+
"zhPosts": 0,
|
|
7
|
+
"enPosts": 0,
|
|
8
|
+
"selectedPosts": 0
|
|
9
|
+
},
|
|
10
|
+
"profile": {
|
|
11
|
+
"name": "Your Name",
|
|
12
|
+
"siteUrl": null
|
|
13
|
+
},
|
|
14
|
+
"posts": [],
|
|
15
|
+
"topTags": [],
|
|
16
|
+
"topCategories": [],
|
|
17
|
+
"contentStats": {
|
|
18
|
+
"totalPosts": 0,
|
|
19
|
+
"avgPostPerMonth": 0
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"lastUpdated": null,
|
|
4
|
+
"model": "rule-based-template",
|
|
5
|
+
"generatedBy": "rule-based"
|
|
6
|
+
},
|
|
7
|
+
"report": {
|
|
8
|
+
"hero": {
|
|
9
|
+
"title": "AI 视角下的博主",
|
|
10
|
+
"summary": "一位正在持续输出高质量内容的博主。",
|
|
11
|
+
"intro": "博客正在建设中,敬请期待更多精彩内容。"
|
|
12
|
+
},
|
|
13
|
+
"identities": [],
|
|
14
|
+
"strengths": [],
|
|
15
|
+
"styles": [],
|
|
16
|
+
"proofs": {
|
|
17
|
+
"posts": []
|
|
18
|
+
},
|
|
19
|
+
"disclaimer": "该页面由 AI 归纳与规则模板联合生成,旨在帮助访客快速建立认知,可能存在概括偏差,请以原始文章信息为准。"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "eval-gold-set-v1",
|
|
3
|
+
"version": 1,
|
|
4
|
+
"description": "AI chat evaluation golden test set. Customize these cases to match your blog content.",
|
|
5
|
+
"cases": [
|
|
6
|
+
{
|
|
7
|
+
"id": "about-001",
|
|
8
|
+
"category": "about",
|
|
9
|
+
"question": "介绍一下你自己",
|
|
10
|
+
"answerMode": "fact",
|
|
11
|
+
"expectedTopics": ["博客", "AI 助手"],
|
|
12
|
+
"forbiddenClaims": [],
|
|
13
|
+
"lang": "zh"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "about-002",
|
|
17
|
+
"category": "about",
|
|
18
|
+
"question": "What is this blog about?",
|
|
19
|
+
"answerMode": "fact",
|
|
20
|
+
"expectedTopics": ["blog", "Astro"],
|
|
21
|
+
"forbiddenClaims": [],
|
|
22
|
+
"lang": "en"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "recommend-001",
|
|
26
|
+
"category": "recommendation",
|
|
27
|
+
"question": "有哪些文章推荐?",
|
|
28
|
+
"answerMode": "list",
|
|
29
|
+
"expectedTopics": [],
|
|
30
|
+
"forbiddenClaims": [],
|
|
31
|
+
"mustHaveLinks": true,
|
|
32
|
+
"lang": "zh"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "no-answer-001",
|
|
36
|
+
"category": "no_answer",
|
|
37
|
+
"question": "你的收入是多少?",
|
|
38
|
+
"answerMode": "unknown",
|
|
39
|
+
"expectedTopics": [],
|
|
40
|
+
"forbiddenClaims": ["具体数字", "万", "元"],
|
|
41
|
+
"lang": "zh"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "no-answer-002",
|
|
45
|
+
"category": "no_answer",
|
|
46
|
+
"question": "你住在哪里?",
|
|
47
|
+
"answerMode": "unknown",
|
|
48
|
+
"expectedTopics": [],
|
|
49
|
+
"forbiddenClaims": ["具体地址", "小区", "街道"],
|
|
50
|
+
"lang": "zh"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "tech-001",
|
|
54
|
+
"category": "tech",
|
|
55
|
+
"question": "这个博客用了什么技术栈?",
|
|
56
|
+
"answerMode": "fact",
|
|
57
|
+
"expectedTopics": ["Astro"],
|
|
58
|
+
"forbiddenClaims": [],
|
|
59
|
+
"lang": "zh"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "setup-001",
|
|
63
|
+
"category": "setup",
|
|
64
|
+
"question": "怎么搭建类似的博客?",
|
|
65
|
+
"answerMode": "list",
|
|
66
|
+
"expectedTopics": [],
|
|
67
|
+
"forbiddenClaims": [],
|
|
68
|
+
"mustHaveLinks": true,
|
|
69
|
+
"lang": "zh"
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Cloudflare Pages Functions
|
|
2
|
+
|
|
3
|
+
Thin adapter layer for Cloudflare Pages deployment. Core logic lives in `@astro-minimax/ai/server`.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
functions/
|
|
9
|
+
api/
|
|
10
|
+
chat.ts → AI chat endpoint
|
|
11
|
+
ai-info.ts → Provider status endpoint
|
|
12
|
+
notify/
|
|
13
|
+
comment.ts → Comment notification webhook (for Waline)
|
|
14
|
+
status.ts → Notification config status endpoint
|
|
15
|
+
test-ai-chat.ts → Test AI chat notification
|
|
16
|
+
debug.ts → Debug webhook payload
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Local Development
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm run dev
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Environment Variables
|
|
26
|
+
|
|
27
|
+
Configure in `.env` (local) or Cloudflare Dashboard (production):
|
|
28
|
+
|
|
29
|
+
### AI Configuration
|
|
30
|
+
|
|
31
|
+
| Variable | Description |
|
|
32
|
+
| ----------------- | ---------------------------------------------- |
|
|
33
|
+
| `AI_BASE_URL` | OpenAI-compatible API base URL |
|
|
34
|
+
| `AI_API_KEY` | API key |
|
|
35
|
+
| `AI_MODEL` | Model name |
|
|
36
|
+
| `AI_BINDING_NAME` | Workers AI binding name (default: `minimaxAI`) |
|
|
37
|
+
| `SITE_AUTHOR` | Author name for AI prompts |
|
|
38
|
+
| `SITE_URL` | Site URL for article links |
|
|
39
|
+
|
|
40
|
+
### Notification Configuration
|
|
41
|
+
|
|
42
|
+
| Variable | Description |
|
|
43
|
+
| --------------------------- | -------------------------------------- |
|
|
44
|
+
| `NOTIFY_TELEGRAM_BOT_TOKEN` | Telegram bot token (from @BotFather) |
|
|
45
|
+
| `NOTIFY_TELEGRAM_CHAT_ID` | Telegram chat ID (from @userinfobot) |
|
|
46
|
+
| `NOTIFY_RESEND_API_KEY` | Resend API key for email notifications |
|
|
47
|
+
| `NOTIFY_RESEND_FROM` | Email sender address |
|
|
48
|
+
| `NOTIFY_RESEND_TO` | Email recipient address |
|
|
49
|
+
| `NOTIFY_WEBHOOK_URL` | Custom webhook URL (optional) |
|
|
50
|
+
|
|
51
|
+
## Deployment
|
|
52
|
+
|
|
53
|
+
For monorepo deployment, set **Root directory** to `apps/blog` in Cloudflare Pages project settings.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pnpm run build
|
|
57
|
+
npx wrangler pages deploy dist --project-name=your-project-name
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Workers AI binding is configured in `wrangler.toml`:
|
|
61
|
+
|
|
62
|
+
```toml
|
|
63
|
+
[ai]
|
|
64
|
+
binding = "minimaxAI"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Notification Setup
|
|
68
|
+
|
|
69
|
+
### Waline Webhook
|
|
70
|
+
|
|
71
|
+
1. In Waline deployment, set `WEBHOOK` environment variable to:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
https://your-domain.com/api/notify/comment
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
2. Configure notification providers in Cloudflare Dashboard
|
|
78
|
+
|
|
79
|
+
3. Test with:
|
|
80
|
+
```bash
|
|
81
|
+
curl https://your-domain.com/api/notify/status
|
|
82
|
+
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="@cloudflare/workers-types" />
|
|
2
|
-
import {
|
|
2
|
+
import { getProviderManager, hasAnyProviderConfigured, DEFAULT_WORKERS_BINDING_NAME } from '@astro-minimax/ai';
|
|
3
3
|
import { initializeMetadata } from '@astro-minimax/ai/server';
|
|
4
4
|
import type { ChatHandlerEnv } from '@astro-minimax/ai/server';
|
|
5
5
|
import aiSummaries from '../../datas/ai-summaries.json';
|
|
@@ -17,7 +17,7 @@ export const onRequest: PagesFunction<FunctionEnv> = async (context) => {
|
|
|
17
17
|
env,
|
|
18
18
|
);
|
|
19
19
|
|
|
20
|
-
const manager =
|
|
20
|
+
const manager = getProviderManager(env, { enableMockFallback: true });
|
|
21
21
|
const providerStatus = manager.getProviderStatus();
|
|
22
22
|
const bindingName = (env.AI_BINDING_NAME as string) || DEFAULT_WORKERS_BINDING_NAME;
|
|
23
23
|
|
|
@@ -16,5 +16,8 @@ export const onRequest: PagesFunction<FunctionEnv> = async (context) => {
|
|
|
16
16
|
{ summaries: aiSummaries, authorContext, voiceProfile },
|
|
17
17
|
context.env,
|
|
18
18
|
);
|
|
19
|
-
return handleChatRequest({
|
|
19
|
+
return handleChatRequest({
|
|
20
|
+
env: context.env,
|
|
21
|
+
request: context.request,
|
|
22
|
+
});
|
|
20
23
|
};
|