30 分钟,从零写第一个大模型后端接口,新手跟着就能跑通
导语:别让「第一步」,拦住你的AI开发之路
我见过很多想入行AI大模型后端开发的新手,刷完了整套Python和FastAPI教程,甚至背完了RAG和Agent的核心原理,却始终迈不出最关键的一步:
写出第一个属于自己的、能正常运行的、可以被前端调用的大模型后端接口。
要么是跟着视频敲完代码,一运行就报错,环境问题、依赖问题、网络问题,卡了3天直接放弃;
要么是只会调官方的SDK Demo,不知道怎么封装成标准的HTTP接口,不知道怎么给前端用;
要么是怕自己零基础、非科班,连代码都看不懂,觉得自己肯定学不会。
今天这篇文章,就是来解决所有新手的痛点的。我承诺:只要你会用电脑、能看懂中文,跟着这篇文章一步步走,30分钟,从零开始,写出第一个完整可运行的大模型后端接口,实现和ChatGPT一模一样的对话能力,包括基础同步对话和流式打字机效果。
全文所有代码都可以直接复制运行,所有新手会踩的坑,我都提前给你踩过了,配套了完整的报错解决方案,零门槛、零前置知识,跟着就能跑通。
一、先给新手吃定心丸:你的前置条件,几乎为零
很多新手还没开始就自我劝退:「我不会Python、我没学过后端、我不懂大模型原理,能学会吗?」
答案是:完全可以。这篇教程的所有内容,都不需要你有任何编程基础、后端知识、大模型算法功底,我会把每一个步骤、每一行代码都讲得明明白白。
1.1 你需要准备的唯一东西
- 一台能正常上网的电脑(Windows/Mac/Linux都可以,无配置要求)
- 一个手机号(用来申请大模型API密钥,免费)
1.2 为什么我们选FastAPI,而不是其他框架?
新手入门,选对工具,就成功了一半。我们全程用Python+FastAPI开发,原因非常简单:
- 零门槛友好:Python语法接近大白话,比Java、Go更容易上手,零基础也能看懂;
- 开发效率拉满:10行代码就能写出一个完整的接口,比Spring Boot、Flask少写80%的模板代码;
- 原生适配AI场景:天生支持异步编程,完美适配大模型API的IO密集型场景,流式输出(打字机效果)实现成本极低;
- 自动生成接口文档:写完代码自动生成可视化的交互式接口文档,不用装Postman,浏览器里就能直接测试接口,对新手极度友好。
1.3 为什么选国产大模型,而不是OpenAI?
这是新手最容易踩的第一个坑:很多教程一上来就用OpenAI API,结果新手没有翻墙工具,连接口都调不通,直接卡在第一步。
我们全程用字节跳动豆包大模型API,核心优势:
- 国内直连,无网络障碍:不需要任何翻墙工具,网络稳定,不会出现超时、连不上的问题;
- 免费额度充足:新用户注册就送大量免费token额度,个人开发测试完全够用,一分钱不用花;
- 完全兼容OpenAI格式:后面你想切换成OpenAI、通义千问、文心一言,只需要改2行代码,零成本切换;
- 大厂稳定保障:接口响应速度快,可用性99.9%,个人测试和生产环境都能用。
二、5分钟搞定前置准备:API密钥申请+环境搭建
2.1 3分钟申请大模型API密钥
这是我们唯一需要提前准备的「通行证」,步骤极其简单,跟着点就行:
- 打开【火山引擎官网】(https://www.volcengine.com/),用手机号注册并登录;
- 顶部搜索框搜索「豆包大模型」,进入产品页面,点击「立即使用」,免费开通服务;
- 进入控制台后,左侧菜单栏找到「API密钥管理」,点击「新建密钥」,创建一个专属的API密钥;
- 复制生成的SK(Secret Access Key),保存到记事本里,后面代码里必须用到,绝对不要泄露给任何人,更不要上传到公开的GitHub仓库!
2.2 2分钟搭建基础开发环境
我们只需要装2个软件,都是免费的,一键安装:
- Python 3.10+:
- 打开Python官网(https://www.python.org/downloads/),下载对应系统的最新版本(3.10及以上都可以);
- 安装的时候,一定要勾选最下方的「Add python.exe to PATH」,这是新手最容易踩的坑,不勾选后面会无法运行Python命令;
- 安装完成后,打开终端(Windows用PowerShell,Mac用终端),输入
python --version和pip --version,能输出版本号,就说明安装成功了。
- VS Code:
- 打开VS Code官网(https://code.visualstudio.com/),下载对应系统的版本,一键安装即可;
- 安装完成后,打开VS Code,在左侧扩展商店里搜索「Python」,安装微软官方的Python插件,方便我们写代码和调试。
三、10分钟完成项目初始化+依赖安装
3.1 创建项目文件夹
- 在电脑上新建一个文件夹,命名为
llm-api-demo,名字可以随便起,不要带中文和空格; - 打开VS Code,点击左上角「文件」→「打开文件夹」,选中刚才新建的
llm-api-demo文件夹,打开。
3.2 创建并激活Python虚拟环境
很多新手会问:为什么要创建虚拟环境?直接装在全局不行吗?
大白话解释:虚拟环境就是给你的项目单独建了一个「独立的Python小房间」,你装的所有依赖包,都只在这个房间里生效,不会影响全局的Python环境,也不会和其他项目的依赖包版本冲突,这是Python开发的标准规范,新手从一开始就要养成好习惯。
操作步骤:
- 在VS Code里,按下快捷键
Ctrl+(Windows)/Command+(Mac),打开终端,终端会自动定位到我们的项目文件夹; - 在终端里输入下面的命令,创建虚拟环境,回车执行:
执行完成后,项目文件夹里会多出一个python -m venv venvvenv文件夹,就说明创建成功了。 - 激活虚拟环境,这一步非常关键,每次打开项目都要先激活虚拟环境:
- Windows系统(PowerShell):
.\venv\Scripts\Activate.ps1 - Mac/Linux系统:
source venv/bin/activate
(venv)的标识,就说明已经进入虚拟环境了。 - Windows系统(PowerShell):
新手常见报错解决方案
如果Windows系统报错「无法加载文件,因为在此系统上禁止运行脚本」,解决方法:
- 用管理员身份打开PowerShell;
- 输入命令:
Set-ExecutionPolicy RemoteSigned,按回车,输入Y确认; - 关闭PowerShell,重新打开VS Code的终端,再执行激活命令,就可以了。
3.3 安装必须的依赖包
在激活了虚拟环境的终端里,输入下面的命令,一键安装所有需要的依赖包,回车执行:
pip install fastapi uvicorn httpx pydantic sse-starlette python-dotenv
每个包的作用,给新手讲明白,不用死记硬背,知道是干嘛的就行:
| 包名 | 核心作用 |
|---|---|
| fastapi | 我们用的Web框架,核心,用来写后端接口 |
| uvicorn | ASGI服务器,用来运行我们写的FastAPI服务 |
| httpx | 异步HTTP客户端,用来调用大模型API,比requests更适配异步场景 |
| pydantic | 数据校验工具,FastAPI原生支持,自动校验前端传的参数,自动生成接口文档 |
| sse-starlette | 流式输出必备工具,实现ChatGPT同款打字机效果 |
| python-dotenv | 环境变量管理工具,用来安全存放API密钥,避免硬编码泄露 |
安装完成后,终端没有报错,就说明我们的环境已经100%准备好了,接下来就可以写代码了。
四、10分钟从零写完整代码,逐行解析,复制就能跑
我们分两步走:先写一个最小Demo,验证环境没问题,拿到第一个成就感;再写完整的大模型接口,逐行解析,新手能完全看懂。
4.1 先跑通最小Demo,拿到第一个成就感
在项目文件夹里,新建一个文件,命名为main.py(必须是.py后缀,不能是.txt),写入下面的代码:
# 1. 导入FastAPI框架
from fastapi import FastAPI
# 2. 初始化FastAPI应用
# title和version会显示在自动生成的接口文档里
app = FastAPI(title="我的第一个大模型后端接口", version="1.0")
# 3. 写一个最简单的接口,用来测试服务是否正常
@app.get("/", summary="Hello World测试接口")
def hello_world():
return {
"code": 0,
"message": "恭喜你!你的第一个FastAPI接口跑通了!",
"data": "Hello AI World!"
}
写完之后,在终端里输入启动服务的命令,回车执行:
uvicorn main:app --reload
看到终端里输出Uvicorn running on http://127.0.0.1:8000,就说明服务启动成功了!
我们来验证一下:
- 打开浏览器,输入
http://127.0.0.1:8000,就能看到我们接口返回的JSON数据,说明服务完全正常; - 打开
http://127.0.0.1:8000/docs,就能看到FastAPI自动给我们生成的可视化交互式接口文档,点击「Try it out」→「Execute」,就能直接测试接口,不用装任何额外的工具,对新手极度友好。
到这里,你已经完成了最关键的一步:写出了第一个能正常运行的后端接口,已经超过了80%只看不做的新手。
4.2 完整的大模型后端接口代码,逐行解析
接下来,我们把完整的大模型接口代码,写入main.py文件里,直接替换掉之前的Demo代码即可,所有代码都有详细注释,新手能看懂每一行的作用。
完整代码(直接复制就能用)
# ------------------------------
# 1. 导入所有需要的依赖包
# ------------------------------
# FastAPI核心框架
from fastapi import FastAPI, HTTPException
# 跨域配置,解决前端调用接口的跨域问题
from fastapi.middleware.cors import CORSMiddleware
# 数据模型定义,用来做请求参数校验
from pydantic import BaseModel
# 异步HTTP客户端,用来调用大模型API
import httpx
# 流式输出SSE协议支持
from sse_starlette.sse import EventSourceResponse
# 环境变量管理,安全存放API密钥
from dotenv import load_dotenv
import os
import asyncio
import json
# ------------------------------
# 2. 基础配置,新手只需要在这里填你的API密钥
# ------------------------------
# 加载.env文件里的环境变量
load_dotenv()
# 你的豆包API密钥,从火山引擎控制台复制过来
# 生产环境绝对不要硬编码,我们用.env文件管理,后面会讲
DOUBAO_API_KEY = os.getenv("DOUBAO_API_KEY", "这里填你复制的API密钥")
# 豆包API请求地址,固定不变
DOUBAO_API_URL = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
# 默认使用的模型,这里用豆包4.0极速版,免费额度可用,响应速度快
DEFAULT_MODEL = "ep-20240801******" # 替换为你自己的模型endpoint ID
# ------------------------------
# 3. 初始化FastAPI应用
# ------------------------------
app = FastAPI(
title="我的第一个大模型后端接口",
description="零基础入门大模型后端开发,完整实现同步对话+流式对话",
version="1.0"
)
# ------------------------------
# 4. 配置CORS跨域中间件,新手必加!
# ------------------------------
# 大白话解释:前端的地址和后端的地址不一样,浏览器会默认拦截请求,加了这个配置,前端就能正常调用接口了
app.add_middleware(
CORSMiddleware,
# 允许所有前端地址访问,生产环境可以改成你的前端域名,比如["https://your-frontend.com"]
allow_origins=["*"],
# 允许所有请求方法,GET/POST/PUT/DELETE等
allow_methods=["*"],
# 允许所有请求头
allow_headers=["*"],
# 允许携带凭证
allow_credentials=True
)
# ------------------------------
# 5. 定义全局异步HTTP客户端
# ------------------------------
# 复用HTTP连接,提升性能,避免每次调用都新建连接
# 服务启动时创建,服务关闭时自动释放
async_client = httpx.AsyncClient(
# 超时时间设置,大模型响应可能需要几秒,设置30秒足够
timeout=httpx.Timeout(30.0, connect=5.0)
)
# 服务关闭时,自动关闭HTTP客户端,释放资源
@app.on_event("shutdown")
async def shutdown_event():
await async_client.aclose()
# ------------------------------
# 6. 定义请求和响应的数据模型
# ------------------------------
# 大白话解释:定义前端传给我们的参数格式,FastAPI会自动校验,参数不对直接返回清晰的错误
# 对话消息模型,单条消息的格式
class ChatMessage(BaseModel):
# 角色,只能是user(用户)、assistant(AI助手)、system(系统提示词)
role: str
# 消息内容
content: str
# 对话请求体,前端传给我们的完整参数
class ChatRequest(BaseModel):
# 对话消息列表,比如[{"role": "user", "content": "你好"}]
messages: list[ChatMessage]
# 模型,可选,不传就用默认模型
model: str | None = None
# 温度值,可选,0-2之间,越高越随机,越低越严谨,默认0.7
temperature: float | None = 0.7
# 是否流式输出,默认False
stream: bool | None = False
# ------------------------------
# 7. 健康检查接口,用来测试服务是否正常
# ------------------------------
@app.get("/health", summary="健康检查接口")
async def health_check():
return {
"code": 0,
"message": "服务运行正常",
"data": {
"status": "running",
"version": "1.0"
}
}
# ------------------------------
# 8. 核心接口1:同步对话接口(非流式,一次性返回完整结果)
# ------------------------------
@app.post("/api/chat", summary="同步对话接口,一次性返回完整结果")
async def chat(chat_request: ChatRequest):
"""
基础对话接口,前端传入对话消息,一次性返回AI的完整回答
"""
# 1. 构建请求大模型的请求头
headers = {
"Authorization": f"Bearer {DOUBAO_API_KEY}",
"Content-Type": "application/json"
}
# 2. 构建请求大模型的请求体
request_body = {
"model": chat_request.model or DEFAULT_MODEL,
"messages": [msg.model_dump() for msg in chat_request.messages],
"temperature": chat_request.temperature,
"stream": False
}
try:
# 3. 异步调用大模型API
response = await async_client.post(
DOUBAO_API_URL,
headers=headers,
json=request_body
)
# 4. 处理异常情况:接口返回非200状态码
response.raise_for_status()
# 5. 解析大模型返回的结果
result = response.json()
ai_reply = result["choices"][0]["message"]["content"]
total_tokens = result["usage"]["total_tokens"]
# 6. 给前端返回标准化的结果
return {
"code": 0,
"message": "success",
"data": {
"reply": ai_reply,
"model": request_body["model"],
"total_tokens": total_tokens
}
}
# 7. 异常处理,给前端返回清晰的错误信息,新手能快速定位问题
except httpx.TimeoutException:
raise HTTPException(status_code=504, detail="大模型API请求超时,请稍后重试")
except httpx.HTTPStatusError as e:
if e.response.status_code == 401:
raise HTTPException(status_code=401, detail="API密钥错误,请检查你的密钥是否正确")
elif e.response.status_code == 403:
raise HTTPException(status_code=403, detail="API权限不足,请检查是否开通了模型服务")
else:
raise HTTPException(status_code=500, detail=f"大模型API调用失败:{e.response.text}")
except Exception as e:
raise HTTPException(status_code=500, detail=f"服务内部错误:{str(e)}")
# ------------------------------
# 9. 核心接口2:流式对话接口(打字机效果,逐字返回)
# ------------------------------
@app.post("/api/chat/stream", summary="流式对话接口,实现ChatGPT同款打字机效果")
async def chat_stream(chat_request: ChatRequest):
"""
流式对话接口,实现打字机效果,AI生成一个字就返回一个字,体验更好
"""
# 1. 构建请求头和请求体
headers = {
"Authorization": f"Bearer {DOUBAO_API_KEY}",
"Content-Type": "application/json"
}
request_body = {
"model": chat_request.model or DEFAULT_MODEL,
"messages": [msg.model_dump() for msg in chat_request.messages],
"temperature": chat_request.temperature,
"stream": True # 开启流式输出
}
# 2. 定义流式生成器,逐字返回AI生成的内容
async def event_generator():
try:
# 异步流式调用大模型API
async with async_client.stream(
"POST",
DOUBAO_API_URL,
headers=headers,
json=request_body
) as response:
# 处理异常状态码
response.raise_for_status()
# 逐行读取大模型返回的流式数据
async for line in response.aiter_lines():
# 过滤空行和非数据行
line = line.strip()
if not line or not line.startswith("data: "):
await asyncio.sleep(0.01)
continue
# 解析SSE数据,去掉"data: "前缀
data = line[6:]
# 流式结束标识,大模型返回[DONE]就说明生成完成了
if data == "[DONE]":
yield {
"event": "done",
"data": "[DONE]"
}
return
# 解析JSON数据,提取逐字生成的内容
try:
json_data = json.loads(data)
delta_content = json_data["choices"][0]["delta"].get("content", "")
# 如果有内容,就通过SSE事件返回给前端
if delta_content:
yield {
"event": "message",
"data": delta_content
}
except json.JSONDecodeError:
continue
except Exception:
continue
# 异常处理,通过SSE事件返回错误信息
except httpx.TimeoutException:
yield {
"event": "error",
"data": json.dumps({"code": 504, "message": "请求超时,请稍后重试"})
}
except Exception as e:
yield {
"event": "error",
"data": json.dumps({"code": 500, "message": f"服务异常:{str(e)}"})
}
# 3. 返回SSE流式响应
return EventSourceResponse(
event_generator(),
media_type="text/event-stream",
ping=2000 # 2秒一次心跳,防止连接被网关断开
)
新手需要修改的2个地方
- 把
DOUBAO_API_KEY的值,替换成你从火山引擎控制台复制的API密钥; - 把
DEFAULT_MODEL的值,替换成你在火山引擎创建的模型endpoint ID(在豆包大模型控制台的「推理接入点」里能找到)。
4.3 密钥安全优化:绝对不要硬编码密钥!
新手最容易犯的致命错误:把API密钥硬编码在代码里,不小心上传到GitHub,被爬虫爬走,被盗刷几十万。
我们用.env文件来管理密钥,绝对安全,步骤如下:
- 在项目文件夹里,新建一个文件,命名为
.env(注意前面有个点,没有后缀名); - 在
.env文件里写入下面的内容:# 你的豆包API密钥 DOUBAO_API_KEY=这里填你复制的API密钥 # 你的模型endpoint ID DEFAULT_MODEL=这里填你的模型endpoint ID - 把
main.py里的硬编码密钥删掉,改成从环境变量读取,代码已经写好了,不用改; - 新建一个
.gitignore文件,写入下面的内容,避免把密钥和虚拟环境上传到Git仓库:# 环境变量文件,绝对不能上传 .env # 虚拟环境文件夹 venv/ # Python缓存文件 __pycache__/ # 日志文件 *.log
到这里,我们的完整代码就写完了,接下来就可以启动服务,测试接口了。
五、5分钟运行服务+接口测试,零额外工具
5.1 启动服务
在激活了虚拟环境的终端里,输入启动命令,回车执行:
uvicorn main:app --reload
看到终端输出Uvicorn running on http://127.0.0.1:8000,没有报错,就说明服务启动成功了!
5.2 用自动生成的接口文档测试接口
FastAPI最友好的地方,就是自动生成了可视化的交互式接口文档,我们不用装任何工具,浏览器里就能直接测试。
- 打开浏览器,输入
http://127.0.0.1:8000/docs,进入接口文档页面; - 找到
/api/chat同步对话接口,点击右上角的「Try it out」,进入测试模式; - 下面的请求体里,已经自动生成了模板,我们只需要修改
messages里的内容,比如:{ "messages": [ { "role": "user", "content": "你好,给我讲一个程序员的冷笑话" } ], "temperature": 0.7, "stream": false } - 点击「Execute」,就能看到接口返回的结果,AI的回答会显示在响应体里,说明我们的接口完全跑通了!
- 同样的方法,你可以测试
/api/chat/stream流式接口,实现打字机效果。
恭喜你!到这里,你已经从零写出了第一个完整的大模型后端接口,实现了和ChatGPT一模一样的对话能力,30分钟的承诺,你已经完成了!
六、新手90%会遇到的报错,全给你解决方案
我把新手最容易遇到的所有报错,都整理好了,遇到问题直接查,就能解决,不用到处搜:
| 常见报错 | 核心原因 | 解决方案 |
|---|---|---|
| 无法将“uvicorn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称 | 没激活虚拟环境,或者没装uvicorn | 1. 重新激活虚拟环境,确保终端前面有(venv)标识;2. 执行pip install uvicorn重新安装 |
| 调用接口返回401 Unauthorized | API密钥错误,或者没填对 | 1. 检查密钥是否和控制台的一致;2. 检查密钥前面有没有多余的空格;3. 确认密钥已经开通了豆包大模型的权限 |
| 调用接口返回403 Forbidden | 模型endpoint ID错误,或者没开通对应模型的服务 | 1. 检查endpoint ID是否正确;2. 去控制台确认模型服务已经开通,有可用额度 |
| 调用接口超时 | 网络问题,或者API地址填错了 | 1. 检查API地址是否正确;2. 确认你的网络能正常访问火山引擎,不用翻墙;3. 把超时时间调长一点 |
| 前端调用接口报CORS跨域错误 | 没配置CORS跨域中间件,或者配置不对 | 1. 确认代码里加了CORSMiddleware;2. allow_origins改成[“*”],允许所有地址访问;3. 重启服务 |
| 流式接口没反应 | 没装sse-starlette,或者前端没按SSE协议处理 | 1. 执行pip install sse-starlette安装依赖;2. 重启服务;3. 用接口文档测试,确认后端能正常返回 |
| 启动服务报错“Address already in use” | 8000端口被占用了 | 1. 关掉其他占用8000端口的程序;2. 启动命令加–port参数,换个端口,比如uvicorn main:app --reload --port 8001 |
七、进阶优化:从Demo到生产环境,你需要做的事
我们现在写的接口,已经能正常运行,但是要放到生产环境给用户用,还需要做一些优化,给新手一个进阶的方向:
- 完善用户管控与接口限流:给每个用户设置单日token限额和接口调用频率限制,避免被恶意刷量,导致账单爆炸;
- 完善容错机制:添加接口重试、熔断降级,大模型API故障的时候,返回兜底内容,避免服务崩溃;
- 添加日志与监控:全链路日志埋点,记录每个用户的请求、token用量、接口耗时,出问题能快速定位;
- 多模型适配:封装统一的模型适配层,支持一键切换豆包、OpenAI、通义千问、文心一言等多个大模型;
- 一键部署上线:把服务打包成Docker镜像,部署到云服务器上,让所有人都能访问你的接口。
八、可选:Java Spring Boot版本完整实现
如果你有Java基础,更习惯用Spring Boot开发,这里给你完整的Spring Boot 3.x版本实现,同样能直接跑通,实现同步+流式对话接口。
8.1 核心依赖(pom.xml)
<dependencies>
<!-- Spring Boot WebFlux,异步非阻塞,适配流式输出 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>3.2.5</version>
</dependency>
<!-- Lombok,简化代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<optional>true</optional>
</dependency>
<!-- Jackson,JSON处理 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.3</version>
</dependency>
</dependencies>
8.2 配置文件(application.yml)
server:
port: 8080
llm:
doubao:
api-key: 你的API密钥
api-url: https://ark.cn-beijing.volces.com/api/v3/chat/completions
default-model: 你的模型endpoint ID
8.3 完整代码实现
package com.llm.demo.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*") // 解决跨域问题
public class LlmChatController {
@Value("${llm.doubao.api-key}")
private String apiKey;
@Value("${llm.doubao.api-url}")
private String apiUrl;
@Value("${llm.doubao.default-model}")
private String defaultModel;
// 初始化WebClient,异步HTTP客户端
private final WebClient webClient = WebClient.create();
private final ObjectMapper objectMapper = new ObjectMapper();
// 对话消息模型
@Data
public static class ChatMessage {
private String role;
private String content;
}
// 对话请求体
@Data
public static class ChatRequest {
private List<ChatMessage> messages;
private String model;
private Float temperature = 0.7f;
private Boolean stream = false;
}
// 健康检查接口
@GetMapping("/health")
public Mono<String> healthCheck() {
return Mono.just("服务运行正常");
}
// 同步对话接口
@PostMapping("/chat")
public Mono<JsonNode> chat(@RequestBody ChatRequest request) {
// 构建请求体
JsonNode requestBody = objectMapper.valueToTree(request);
((com.fasterxml.jackson.databind.node.ObjectNode) requestBody).put("model", request.getModel() == null ? defaultModel : request.getModel());
((com.fasterxml.jackson.databind.node.ObjectNode) requestBody).put("stream", false);
// 调用大模型API
return webClient.post()
.uri(apiUrl)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(requestBody)
.retrieve()
.bodyToMono(JsonNode.class)
.onErrorResume(e -> Mono.error(new RuntimeException("大模型调用失败:" + e.getMessage())));
}
// 流式对话接口,实现打字机效果
@PostMapping("/chat/stream")
public Flux<ServerSentEvent<String>> chatStream(@RequestBody ChatRequest request) {
// 构建请求体
JsonNode requestBody = objectMapper.valueToTree(request);
((com.fasterxml.jackson.databind.node.ObjectNode) requestBody).put("model", request.getModel() == null ? defaultModel : request.getModel());
((com.fasterxml.jackson.databind.node.ObjectNode) requestBody).put("stream", true);
// 流式调用大模型API,返回SSE事件
return webClient.post()
.uri(apiUrl)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(requestBody)
.retrieve()
.bodyToFlux(String.class)
.filter(line -> line.startsWith("data: ") && !line.equals("data: [DONE]"))
.map(line -> {
try {
String jsonData = line.substring(6);
JsonNode jsonNode = objectMapper.readTree(jsonData);
String content = jsonNode.get("choices").get(0).get("delta").get("content").asText("");
return ServerSentEvent.<String>builder()
.event("message")
.data(content)
.build();
} catch (Exception e) {
return ServerSentEvent.<String>builder()
.event("error")
.data("解析失败")
.build();
}
})
.concatWithValues(ServerSentEvent.<String>builder().event("done").data("[DONE]").build())
.onErrorResume(e -> Flux.just(ServerSentEvent.<String>builder().event("error").data(e.getMessage()).build()));
}
}
结尾:你的AI开发之路,从这里正式开始
很多人觉得,AI大模型开发门槛很高,需要深厚的算法功底、数学基础,其实不是的。
对于99%的人来说,我们不需要去造大模型这个「发动机」,我们只需要学会用这个发动机,造出能解决实际问题的产品,而写好后端接口,就是你造产品的第一步。
今天你用30分钟,写出了第一个大模型后端接口,这不是终点,而是你AI后端开发之路的起点。后面你可以继续学习RAG知识库、Agent智能体,把你的接口变成更强大的AI产品。
如果跟着教程跑通了,欢迎在评论区留言「跑通了」,分享你的喜悦;如果遇到了任何问题,也可以在评论区留言,我会一一回复解答。
需要本文完整的代码工程包、接口调试教程、部署上线教程的同学,点赞+收藏+关注,评论区留言「接口源码」,我会一一分享给你。
更多推荐
所有评论(0)