Files
zhuangang/topics/frontend/ssr/examples/next-ai-chat/app/api/chat/route.ts
T

36 lines
1.5 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.
// 不自动运行(Next.js 路由处理器,npm run dev 后 POST /api/chat)
// 服务端调用大模型并以流的形式返回;模型密钥只在服务端,浏览器拿不到。
export const runtime = "nodejs";
async function* fakeLLM(question: string, signal: AbortSignal): AsyncGenerator<string> {
// 真实项目:调用模型 SDK 的流式接口,并把 signal 传进去
const words = `关于“${question}”:签收 7 天内可以无理由退货。`.split("");
for (const w of words) {
if (signal.aborted) return; // 用户停止或断开:不再继续生成(节省费用)
await new Promise((r) => setTimeout(r, 30));
yield w;
}
}
export async function POST(request: Request): Promise<Response> {
const { question } = (await request.json()) as { question?: unknown };
if (typeof question !== "string" || question.length === 0 || question.length > 500) {
return Response.json({ error: "question 必须是 1~500 字的字符串" }, { status: 400 });
}
const encoder = new TextEncoder();
const stream = new ReadableStream<Uint8Array>({
async start(controller) {
try {
for await (const token of fakeLLM(question, request.signal)) {
controller.enqueue(encoder.encode(token));
}
} finally {
controller.close();
}
},
});
return new Response(stream, {
headers: { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-cache", "X-Accel-Buffering": "no" },
});
}