Compare commits

..

2 Commits

Author SHA1 Message Date
posimai e9f5b4f6d4 chore: update posimai-guard submodule pointer 2026-04-25 00:15:18 +09:00
posimai 7311db08d8 fix(together): remove gemini-2.0-flash fallback, add 503 retry for 2.5-flash
posimai-together プロジェクトで gemini-2.0-flash が limit:0 のため除外。
gemini-2.5-flash の 503(一時高負荷)は 5 秒待ってリトライするように変更。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 00:12:48 +09:00
2 changed files with 19 additions and 8 deletions

@ -1 +1 @@
Subproject commit 6ab7939676e2ef9bb9ab07089e99b815023e92af Subproject commit 27bcc64b84f71f87af891950ca302fc9c55e106c

View File

@ -2703,10 +2703,10 @@ ${excerpt}
const bodyStart = fullContent.search(/^#{1,2}\s/m); const bodyStart = fullContent.search(/^#{1,2}\s/m);
const excerpt = (bodyStart >= 0 ? fullContent.slice(bodyStart) : fullContent).slice(0, 4000); const excerpt = (bodyStart >= 0 ? fullContent.slice(bodyStart) : fullContent).slice(0, 4000);
const prompt = `以下の記事を分析して、JSONのみを返してくださいコードブロック不要\n\n{"summary":"1〜2文の日本語要約","tags":["タグ1","タグ2","タグ3"]}\n\n- summary: 読者が読む価値があるかを判断できる1〜2文\n- tags: 内容を表す具体的な日本語タグを2〜4個。「その他」は絶対に使わないこと。内容が不明な場合でも最も近いカテゴリを選ぶ例: AI, テクノロジー, ビジネス, 健康, 旅行, 料理, スポーツ, 政治, 経済, エンタメ, ゲーム, 科学, デザイン, ライフスタイル, 教育, 環境, 医療, 法律, 文化, 歴史)\n\n記事:\n${excerpt}`; const prompt = `以下の記事を分析して、JSONのみを返してくださいコードブロック不要\n\n{"summary":"1〜2文の日本語要約","tags":["タグ1","タグ2","タグ3"]}\n\n- summary: 読者が読む価値があるかを判断できる1〜2文\n- tags: 内容を表す具体的な日本語タグを2〜4個。「その他」は絶対に使わないこと。内容が不明な場合でも最も近いカテゴリを選ぶ例: AI, テクノロジー, ビジネス, 健康, 旅行, 料理, スポーツ, 政治, 経済, エンタメ, ゲーム, 科学, デザイン, ライフスタイル, 教育, 環境, 医療, 法律, 文化, 歴史)\n\n記事:\n${excerpt}`;
const modelsToTry = ['gemini-2.5-flash', 'gemini-2.0-flash']; // gemini-2.0-flash は posimai-together プロジェクトで limit:0 のため除外
for (const modelName of modelsToTry) { for (let attempt = 0; attempt < 2; attempt++) {
try { try {
const model = togetherGenAI.getGenerativeModel({ model: modelName }); const model = togetherGenAI.getGenerativeModel({ model: 'gemini-2.5-flash' });
const timeoutP = new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 30000)); const timeoutP = new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 30000));
const result = await Promise.race([model.generateContent(prompt), timeoutP]); const result = await Promise.race([model.generateContent(prompt), timeoutP]);
const raw = result.response.text().trim(); const raw = result.response.text().trim();
@ -2719,7 +2719,13 @@ ${excerpt}
} }
break; break;
} catch (aiErr) { } catch (aiErr) {
console.error(`[together archive AI] ${modelName} share=${shareId}`, aiErr.message); console.error(`[together archive AI] attempt=${attempt + 1} share=${shareId}`, aiErr.message);
// 503一時高負荷は5秒待って1回だけリトライ
if (attempt === 0 && aiErr.status === 503) {
await new Promise(r => setTimeout(r, 5000));
} else {
break;
}
} }
} }
} }
@ -2762,9 +2768,9 @@ ${excerpt}
const excerpt = (bodyStart >= 0 ? share.full_content.slice(bodyStart) : share.full_content).slice(0, 4000); const excerpt = (bodyStart >= 0 ? share.full_content.slice(bodyStart) : share.full_content).slice(0, 4000);
const prompt = `以下の記事を分析して、JSONのみを返してくださいコードブロック不要\n\n{"summary":"1〜2文の日本語要約","tags":["タグ1","タグ2","タグ3"]}\n\n- summary: 読者が読む価値があるかを判断できる1〜2文\n- tags: 内容を表す具体的な日本語タグを2〜4個。「その他」は絶対に使わないこと\n\n記事:\n${excerpt}`; const prompt = `以下の記事を分析して、JSONのみを返してくださいコードブロック不要\n\n{"summary":"1〜2文の日本語要約","tags":["タグ1","タグ2","タグ3"]}\n\n- summary: 読者が読む価値があるかを判断できる1〜2文\n- tags: 内容を表す具体的な日本語タグを2〜4個。「その他」は絶対に使わないこと\n\n記事:\n${excerpt}`;
let rearchiveDone = false; let rearchiveDone = false;
for (const modelName of ['gemini-2.5-flash', 'gemini-2.0-flash']) { for (let attempt = 0; attempt < 2; attempt++) {
try { try {
const model = togetherGenAI.getGenerativeModel({ model: modelName }); const model = togetherGenAI.getGenerativeModel({ model: 'gemini-2.5-flash' });
const timeoutP = new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 30000)); const timeoutP = new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 30000));
const result = await Promise.race([model.generateContent(prompt), timeoutP]); const result = await Promise.race([model.generateContent(prompt), timeoutP]);
const raw = result.response.text().trim(); const raw = result.response.text().trim();
@ -2775,7 +2781,12 @@ ${excerpt}
rearchiveDone = true; rearchiveDone = true;
break; break;
} catch (e) { } catch (e) {
console.error(`[rearchive ${modelName}]`, shareId, e.message); console.error(`[rearchive attempt=${attempt + 1}]`, shareId, e.message);
if (attempt === 0 && e.status === 503) {
await new Promise(r => setTimeout(r, 5000));
} else {
break;
}
} }
} }
if (!rearchiveDone) { if (!rearchiveDone) {