feat: 首次推送到Gitea - 完整项目代码 + 安全加固 + 知识库
This commit is contained in:
@@ -11,7 +11,7 @@ const sep = base.includes("?") ? "&" : "?";
|
||||
const connectionString = `${base}${sep}connection_limit=20&pool_timeout=30`;
|
||||
const adapter = new PrismaMariaDb(connectionString);
|
||||
const prisma = new PrismaClient({ adapter });
|
||||
const openai = new OpenAI({ apiKey: process.env.DEEPSEEK_API_KEY, baseURL: "https://api.deepseek.com/v1", timeout: 120000, maxRetries: 2 });
|
||||
const openai = new OpenAI({ apiKey: process.env.DEEPSEEK_API_KEY, baseURL: "https://api.deepseek.com", timeout: 120000, maxRetries: 2 });
|
||||
|
||||
const EXTRACT_PROMPT = `你是一个AI工具信息提取助手。从以下科技新闻内容中,提取出现的AI工具/产品信息。只提取明确提到的AI软件工具、AI平台、AI产品,不要提取开源项目库(GitHub仓库)、不要提取硬件、芯片。每个工具返回以下信息(如果信息不足则跳过该工具):
|
||||
|
||||
@@ -108,6 +108,27 @@ async function main() {
|
||||
...(await prisma.pendingTool.findMany({ select: { websiteUrl: true } })).map((t) => t.websiteUrl || ""),
|
||||
]);
|
||||
|
||||
// ---- 预筛:只对"标题即宣告新 AI 工具/产品"的新闻调用 AI,避免逐条调用(40 次/天 → ≤15 次/天)----
|
||||
const NEG_TITLE_RE = /财报|股价|裁员|诉讼|处罚|召回|人事任命|评级|监管|关税|事故|禁令|上市申请|营收|亏损|融资|涨停|跌停|关停|下线|停运|放弃|炒作|愚弄|辟谣|传言/;
|
||||
const ACTION_RE = /发布|上线|推出|开源|开放|内测|公测|首发|新增|更新|升级|亮相|登场|宣布/;
|
||||
// 强 AI 主体词:命中即认为"可能是新 AI 工具/产品"(\bai\b 兼顾 "AI工具" 且不误命中 email/available)
|
||||
const AI_STRONG_RE = /\bai\b|大模型|多模态|生成式|智能体|\bagent|copilot|\bllm\b|\bgpt\b|chatgpt|openai|anthropic|deepseek|claude|gemini|midjourney|\bsora\b|豆包|通义|文心|kimi|即梦|可灵|扣子|智谱/;
|
||||
// 泛 AI 词:单独出现不足以判定,需标题配套动作词
|
||||
const AI_WEAK_RE = /模型|助手|生成|对话|语音|图像|视频|编程|插件|工具|平台|\bapi\b|算法|推理/;
|
||||
// 开源项目版本更新(如 "KnowForge 2026.0.5 发布")不是"新 AI 工具",prompt 已明确排除
|
||||
const CHANGELOG_RE = /\d+\.\d+/;
|
||||
const likelyTool = (t) => {
|
||||
const title = (t.title || "").trim();
|
||||
const titleLow = title.toLowerCase();
|
||||
if (NEG_TITLE_RE.test(title) && !ACTION_RE.test(title)) return false; // 财经/负面类
|
||||
if (CHANGELOG_RE.test(title) && /发布|更新|新增|升级/.test(title) && !AI_STRONG_RE.test(titleLow)) return false; // 版本更新
|
||||
if (AI_STRONG_RE.test(titleLow)) return true; // 标题含强 AI 主体词
|
||||
return ACTION_RE.test(title) && AI_WEAK_RE.test(titleLow); // 标题含"动作词 + 泛 AI 词"
|
||||
};
|
||||
const MAX_AI_CALLS = 15; // 单次运行 AI 调用上限(成本保护)
|
||||
let aiCalls = 0;
|
||||
let prefiltered = 0;
|
||||
|
||||
const categoryMap = {};
|
||||
const categories = await prisma.category.findMany({ select: { id: true, name: true, slug: true } });
|
||||
for (const c of categories) {
|
||||
@@ -132,8 +153,11 @@ async function main() {
|
||||
console.log(` 获取 ${news.length} 条`);
|
||||
|
||||
for (const item of news) {
|
||||
// 预筛:非"疑似新工具"的新闻直接跳过,不消耗 AI 调用
|
||||
if (!likelyTool(item) || aiCalls >= MAX_AI_CALLS) { prefiltered++; continue; }
|
||||
const text = `${item.title} ${item.content}`;
|
||||
try {
|
||||
aiCalls++;
|
||||
const completion = await withRetry(async () => {
|
||||
return await openai.chat.completions.create({
|
||||
model: process.env.DEEPSEEK_MODEL || "deepseek-v4-pro",
|
||||
@@ -191,11 +215,13 @@ async function main() {
|
||||
|
||||
const result = {
|
||||
totalNews,
|
||||
prefiltered,
|
||||
aiCalls,
|
||||
foundTools,
|
||||
importedTools,
|
||||
duration: `${(duration / 1000).toFixed(1)}s`,
|
||||
};
|
||||
console.log(`\n🏁 [Task1] 完成: 新闻${totalNews}条, 发现${foundTools}个, 入库${importedTools}个, 耗时${result.duration}`);
|
||||
console.log(`\n🏁 [Task1] 完成: 新闻${totalNews}条, 预筛跳过${prefiltered}条, AI调用${aiCalls}次, 发现${foundTools}个, 入库${importedTools}个, 耗时${result.duration}`);
|
||||
if (errors.length > 0) console.log(` 错误: ${errors.slice(0, 3).join("; ")}`);
|
||||
|
||||
await prisma.taskLog.create({
|
||||
|
||||
Reference in New Issue
Block a user