在命令行里跑通大模型只是开始,真正落地要把它变成一个用户能访问的 Web 服务。这篇教程用 FastAPI 搭后端、原生前端调用,完整实现一个带流式输出的对话网页,涵盖从接口封装到部署上线的每一步。
系统架构 一个典型的大模型 Web 应用分三层:
graph LR
A[浏览器前端] -->|HTTP 请求| B[FastAPI 后端]
B -->|调用| C[大模型 API]
C -->|返回| B
B -->|流式响应| A
API Key 只放在后端,绝不能暴露给前端,这是安全底线。
前置准备 pip install fastapi uvicorn openai
并在后端环境设置好 OPENAI_API_KEY。
步骤一:搭建后端骨架 新建 main.py,创建 FastAPI 应用:
from fastapi import FastAPIfrom fastapi.middleware.cors import CORSMiddlewarefrom pydantic import BaseModelapp = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*" ], allow_methods=["*" ], allow_headers=["*" ], ) class ChatRequest (BaseModel ): message: str
步骤二:封装普通对话接口 import osfrom openai import OpenAIclient = OpenAI(api_key=os.getenv("OPENAI_API_KEY" )) @app.post("/chat" ) def chat (req: ChatRequest ): resp = client.chat.completions.create( model="gpt-4o-mini" , messages=[{"role" : "user" , "content" : req.message}], ) return {"reply" : resp.choices[0 ].message.content}
步骤三:加上流式接口 流式输出让回答像打字一样逐字出现,体验更好。这里用 SSE(Server-Sent Events):
from fastapi.responses import StreamingResponse@app.post("/chat-stream" ) def chat_stream (req: ChatRequest ): def generate (): stream = client.chat.completions.create( model="gpt-4o-mini" , messages=[{"role" : "user" , "content" : req.message}], stream=True , ) for chunk in stream: delta = chunk.choices[0 ].delta.content or "" yield f"data: {delta} \n\n" yield "data: [DONE]\n\n" return StreamingResponse(generate(), media_type="text/event-stream" )
步骤四:启动后端 uvicorn main:app --reload --port 8000
看到 Uvicorn running on http://127.0.0.1:8000 即启动成功。
步骤五:前端调用 新建 index.html,用 fetch 读取流式响应:
<input id ="input" placeholder ="输入问题" /> <button onclick ="send()" > 发送</button > <div id ="output" > </div > <script > async function send ( ) { const message = document .getElementById ("input" ).value ; const output = document .getElementById ("output" ); output.textContent = "" ; const resp = await fetch ("http://127.0.0.1:8000/chat-stream" , { method : "POST" , headers : {"Content-Type" : "application/json" }, body : JSON .stringify ({message}), }); const reader = resp.body .getReader (); const decoder = new TextDecoder (); while (true ) { const {done, value} = await reader.read (); if (done) break ; const text = decoder.decode (value); for (const line of text.split ("\n" )) { if (line.startsWith ("data: " )) { const content = line.slice (6 ); if (content !== "[DONE]" ) output.textContent += content; } } } } </script >
一次完整请求的时序
sequenceDiagram
participant B as 浏览器
participant S as FastAPI 后端
participant M as 大模型
B->>S: POST /chat-stream 用户消息
S->>M: 转发请求 stream 开启
M-->>S: 逐块返回内容
S-->>B: SSE 逐块推送
B->>B: 实时渲染到页面
步骤六:部署上线
后端:用 uvicorn main:app --host 0.0.0.0 --port 8000 生产启动,配合 Nginx 反向代理
前端:静态文件可托管到 Vercel、Netlify 或对象存储
全站用 HTTPS,避免流式请求被中间层缓冲
API Key 用环境变量或密钥管理服务注入,绝不写进代码库
常见问题
前端报跨域错误:检查后端 CORS 配置和 allow_origins
流式不逐字、一次性返回:确认没被 Nginx 缓冲,关闭 proxy_buffering
请求超时:大模型响应慢,调大网关和客户端的超时时间
Key 泄漏:立即在控制台吊销,并排查是否误提交到 Git
小结 把大模型接入 Web 应用的主线是:后端用 FastAPI 封装模型调用(Key 藏在服务端)、用 SSE 实现流式输出、前端用 fetch 逐块渲染。掌握这套结构后,再加上会话管理、鉴权和限流,就能扩展成一个生产可用的 AI 应用。