前言
我使用的是硅基流動中通義千問免費的大模型:
我的技術棧使用的 Next14.2 全棧框架。
代碼結構
需要使用的庫:
npm i ai openai
目錄結構:
基礎測試頁面 test-openai/page.tsx:
'use client';import { useChat } from 'ai/react';export default function TestDeepseek() {const { messages, input, handleInputChange, handleSubmit } = useChat({api: '/api/chat/openai',});return (<div className="flex flex-col w-full max-w-md py-24 mx-auto stretch"><h1 className="text-2xl font-bold mb-4">Deepseek 聊天測試</h1>{messages.map(message => (<div key={message.id} className="whitespace-pre-wrap mb-4 p-3 border rounded-lg"><div className="font-bold">{message.role === 'user' ? '用戶: ' : 'AI: '}</div><div className="mt-1">{message.content}</div></div>))}<form onSubmit={handleSubmit} className="mt-4"><inputclassName="w-full p-2 border border-gray-300 rounded shadow-sm dark:bg-gray-800 dark:border-gray-700"value={input}placeholder="輸入消息..."onChange={handleInputChange}/><button type="submit" className="mt-2 w-full p-2 bg-blue-500 text-white rounded hover:bg-blue-600">發送</button></form></div>);
}
后端接口 app/api/chat/openai/route.ts:
import { handleChatRequest } from '@/lib/openai';
import { NextRequest, NextResponse } from 'next/server';
import { MessageRequestBody } from '@/types/chat';// 設置最大響應時間為30秒
export const maxDuration = 30;/*** 處理POST請求,使用QwQ-32B模型進行聊天* * @param request NextRequest請求對象* @returns 返回流式響應*/
export async function POST(request: NextRequest) {try {// 從請求中獲取消息數據const { messages } = (await request.json()) as MessageRequestBody;if (!messages || !Array.isArray(messages)) {return NextResponse.json({ error: '無效的消息格式' },{ status: 400 });}// 調用QwQ-32B處理函數并返回流式響應return handleChatRequest(messages);} catch (error) {console.error('處理QwQ-32B請求時出錯:', error);return NextResponse.json({ error: '處理請求時發生錯誤: ' + (error instanceof Error ? error.message : String(error)) },{ status: 500 });}
}
lib/openai.ts
openai 規范調用大模型可以參考 deepseek文檔:https://api-docs.deepseek.com/zh-cn/
也可以參考硅基流動的文檔:https://docs.siliconflow.cn/cn/userguide/quickstart
import { Message } from '@/types/chat';
import { NextResponse } from 'next/server';
import OpenAI from 'openai';// 創建自定義OpenAI實例,使用SiliconFlow API
const openai = new OpenAI({apiKey: process.env.SILICONFLOW_API_KEY!,baseURL: process.env.SILICONFLOW_API_BASE!,
});/*** 處理聊天請求的函數* 使用SiliconFlow API處理消息并返回流式響應* * @param messages 聊天消息數組* @returns 流式響應*/
export async function handleChatRequest(messages: Message[]) {try {// 檢查API密鑰是否配置if (!process.env.SILICONFLOW_API_KEY) {console.error('SiliconFlow API密鑰未配置');return NextResponse.json({ error: '未配置SiliconFlow API密鑰,請在.env文件中設置SILICONFLOW_API_KEY' },{ status: 500 });}// 檢查API基礎URL是否配置if (!process.env.SILICONFLOW_API_BASE) {console.error('SiliconFlow API基礎URL未配置');return NextResponse.json({ error: '未配置SiliconFlow API基礎URL,請在.env文件中設置SILICONFLOW_API_BASE' },{ status: 500 });}// 將消息格式轉換為OpenAI格式const formattedMessages = messages.map(msg => ({role: msg.role,content: msg.content}));// 使用SiliconFlow API創建流式響應const response = await openai.chat.completions.create({model: 'Qwen/QwQ-32B', // 使用SiliconFlow提供的QwQ-32B模型messages: formattedMessages,stream: true,});// 創建并返回流式響應const encoder = new TextEncoder();const stream = new ReadableStream({async start(controller) {// 處理流式響應for await (const chunk of response) {const text = chunk.choices[0]?.delta?.content || '';if (text) {controller.enqueue(encoder.encode(text));}}controller.close();},});return new Response(stream, {headers: {'Content-Type': 'text/plain; charset=utf-8','Cache-Control': 'no-cache',},});} catch (error) {console.error('SiliconFlow API調用錯誤:', error);return NextResponse.json({ error: '調用SiliconFlow API時發生錯誤: ' + (error instanceof Error ? error.message : String(error)) },{ status: 500 });}
}
.env
# SILICONFLOW API密鑰
SILICONFLOW_API_KEY=YOUR_API_KEY
SILICONFLOW_API_BASE=https://api.siliconflow.cn/v1# 其他環境變量