Files
zhuiguang-ai/src/app/api/admin/daily-reports/generate/route.ts
T

89 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { NextResponse } from "next/server";
import { requireAdmin } from "@/lib/admin-auth";
import { extractJSON } from "@/lib/utils";
import OpenAI from "openai";
import { badRequest, notFound, serverError } from "@/lib/api-error";
// 必须 force-dynamic,否则 build 期的 page data collection 会触发模块求值
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
// 懒加载 OpenAI client:build 期模块求值时不会触发 SDK 构造
let _openai: OpenAI | null = null;
function getOpenAI(): OpenAI {
if (!_openai) {
_openai = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: "https://api.deepseek.com",
});
}
return _openai;
}
const DAILY_PROMPT = `你是AI行业资深分析师。请为{date}生成一份AI日报,包含6-8条当日最重要的AI行业热点新闻。
要求:
1. 每条新闻必须有真实的新闻事件基础,不能编造
2. 每条新闻必须覆盖不同分类维度,确保多样性
3. 标题简洁有力(20字以内),摘要精炼(50字以内),详情深入(100-200字)
4. 优先关注中国AI行业动态,兼顾全球重要事件
5. 分类标注规则(必须使用以下key值):
- model:模型前沿(LLM/多模态新模型发布、架构创新、训练方法突破)
- product:产品落地(AI产品发布/更新、C端应用上线、B端解决方案、新功能)
- opensource:开源生态(开源项目动态、框架更新、开源社区大事件)
- business:商业产业(投融资、收购并购、财报营收、公司战略、行业趋势)
- policy:政策治理(AI法规政策、监管动态、伦理治理、国际AI治理)
- insight:深度洞察(行业领袖观点、深度分析报告、学术研究前沿)
返回纯JSON格式:
{
"title": "AI日报:{date} 核心要点概览",
"summary": "今日AI行业整体趋势概述(100字以内)",
"items": [
{
"category": "model",
"title": "新闻标题",
"summary": "一句话摘要",
"detail": "详细内容描述",
"sourceUrl": "",
"hotScore": 85
}
]
}
hotScore热度评分规则(0-100)`;
export async function POST(request: Request) {
const authCheck = await requireAdmin();
if (authCheck) return authCheck;
try {
const body = await request.json();
const date = body.date || new Date().toLocaleDateString("zh-CN");
const prompt = DAILY_PROMPT.replace(/\{date\}/g, date);
const completion = await getOpenAI().chat.completions.create({
model: "deepseek-v4-pro",
messages: [{ role: "user", content: prompt }],
temperature: 0.7,
});
const content = completion.choices[0]?.message?.content;
if (!content) {
return NextResponse.json({ error: "生成内容为空" }, { status: 500 });
}
let parsed;
try {
parsed = extractJSON(content);
} catch {
return NextResponse.json({ error: "无法解析AI返回的JSON", raw: content }, { status: 422 });
}
return NextResponse.json({ success: true, data: parsed });
} catch (error) {
return serverError(error);
}
}