Skip to content

Commit 41597aa

Browse files
committed
Split AI prompts by title language
1 parent dbc51f2 commit 41597aa

2 files changed

Lines changed: 29 additions & 13 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ RSS Reader 是一个纯前端应用,数据保存在本机浏览器;RSS 代
1111
- 配置同步:只导出订阅 URL、文件夹和设置,不导出文章缓存和正文内容。
1212
- 可分享文章路径:打开文章后 URL 会带上文章路径,方便复制、收藏和回到同一篇文章。
1313
- 内置 RSS 代理:解决浏览器直接请求 RSS 时遇到的 CORS、HTTPS 和混合内容问题。
14-
- AI 阅读模式:中文文章生成摘要;英文等非中文文章生成少量摘要和全文中文翻译
14+
- AI 阅读模式:标题含中文的文章生成摘要;英文等非中文标题的文章直接全文翻译成中文
1515
- Cloudflare Access 支持:`/rss` 可以公开,`/ai/*` 可以单独加登录保护,避免公开消耗你的模型额度。
1616
- 桌面版本:Electron 版本可以直接抓取 RSS,不需要额外代理。
1717

@@ -47,7 +47,7 @@ npm run app:dist
4747
- `GET /rss?url={url}`:RSS 代理,默认公开。
4848
- `GET /health`:Worker 健康检查。
4949
- `GET /ai/health`:AI 路由健康检查,也可用来触发 Cloudflare Access 登录。
50-
- `POST /ai/responses`:AI 摘要和翻译,转发到 OpenAI Responses API 兼容接口。
50+
- `POST /ai/responses`:AI 摘要或全文翻译,转发到 OpenAI Responses API 兼容接口。
5151

5252
本地启动代理:
5353

server/proxy.js

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ async function handleAiRequest(request, config) {
9191
try {
9292
const payload = await request.json();
9393
const article = normalizeAiArticlePayload(payload);
94+
const isChineseArticle = hasChineseText(article.title);
9495
const upstream = await fetch(`${aiConfig.baseUrl}/responses`, {
9596
method: "POST",
9697
headers: {
@@ -99,7 +100,7 @@ async function handleAiRequest(request, config) {
99100
},
100101
body: JSON.stringify({
101102
model: aiConfig.model,
102-
instructions: buildAiInstructions(),
103+
instructions: buildAiInstructions(isChineseArticle),
103104
input: buildAiInput(article),
104105
max_output_tokens: aiConfig.maxOutputTokens,
105106
store: false,
@@ -160,19 +161,30 @@ function normalizeAiArticlePayload(payload) {
160161
};
161162
}
162163

163-
function buildAiInstructions() {
164-
return [
164+
function buildAiInstructions(isChineseArticle) {
165+
const sharedRules = [
165166
"你是 RSS 阅读器内置的中文阅读助手。",
166-
"先判断文章主要语言。",
167-
"如果文章主要语言是中文,只输出少量中文总结,不要翻译。",
168-
"如果文章主要语言不是中文,先输出少量中文总结,再输出全文简体中文翻译。",
169-
"非中文文章的总结要短,只保留 3 到 5 个核心要点;全文翻译必须覆盖原文正文,不要只概括,不要省略主要段落。",
170-
"翻译要自然、准确,保留原文信息顺序、段落层次、列表关系和必要术语。",
171167
"输出必须是可直接插入页面的 HTML 片段,不要 Markdown,不要代码围栏。",
172168
"只允许使用 h2、h3、p、ul、ol、li、strong、em、blockquote 标签。",
173-
"中文文章结构:h2 标题“AI 摘要”,后面给出摘要。",
174-
"非中文文章结构:h2 标题“AI 摘要”,后面给出短摘要;再给出 h2 标题“全文翻译”,后面给出完整翻译。",
175-
"不要编造原文没有的信息;如果原文内容明显不完整,在摘要中简短说明。",
169+
"不要编造原文没有的信息;如果原文内容明显不完整,简短说明。",
170+
];
171+
172+
if (isChineseArticle) {
173+
return [
174+
...sharedRules,
175+
"这篇文章的标题包含中文字符,按中文文章处理。",
176+
"任务:只输出简体中文摘要,不要翻译正文,不要输出全文改写。",
177+
"结构:先给出 h2 标题“AI 摘要”,后面用 3 到 7 个要点或短段落概括核心事实、背景、结论和不确定性。",
178+
].join("\n");
179+
}
180+
181+
return [
182+
...sharedRules,
183+
"这篇文章的标题不包含中文字符,按非中文文章处理。",
184+
"任务:只输出全文简体中文翻译,不要输出摘要,不要输出要点,不要评价文章。",
185+
"结构:先给出 h2 标题“全文翻译”,后面给出完整翻译。",
186+
"翻译必须覆盖原文正文,不要只概括,不要省略主要段落。",
187+
"翻译要自然、准确,保留原文信息顺序、段落层次、列表关系和必要术语。",
176188
].join("\n");
177189
}
178190

@@ -206,6 +218,10 @@ function extractResponseText(result) {
206218
.trim();
207219
}
208220

221+
function hasChineseText(value) {
222+
return /[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/u.test(String(value || ""));
223+
}
224+
209225
function normalizeBaseUrl(value) {
210226
const url = new URL(String(value || DEFAULT_AI_BASE_URL));
211227
url.pathname = url.pathname.replace(/\/+$/, "");

0 commit comments

Comments
 (0)