一、引言
大模型的里里外外我们都进行了很多细节的讲解,但大模型的部署引用还没有涉及太多,今天我们重点讲一下模型的接口发布,以及利用Postman工具的鉴权调试,Postman 是一款轻量、易用的 API 调试与测试工具,无需编写复杂代码即可快速验证接口的可用性,是本地大模型 API 开发、调试阶段的首选工具。相比于浏览器的自动生成文档页面,Postman 更贴近实际业务中客户端调用 API的真实场景,如后端服务、移动端调用),能直观验证鉴权逻辑、参数传递、返回结果是否符合预期。
今天我们将针对本地大模型 API 的两种鉴权方式:API Key和极简 JWT,详细讲解 Postman 的调用步骤,覆盖从请求配置到完整调用的全流程,让我们能快速上手并实际应用。

二、基础知识
1. 核心概念
- **大模型本地 API 服务:**把本地电脑或服务器上的大模型,变成一个 "可随时呼叫的工具人"。不用连云端,本地就能通过指令调用它干活,数据全程不泄露。
- **FastAPI 封装:**给 "工具人" 装一个 "标准化服务窗口"。让不同程序(比如 APP、网页)都能按统一规则跟大模型沟通,而且这个窗口响应快、还会自动生成使用说明。
- **接口鉴权:**给 "服务窗口" 装一把 "安全锁"。只允许有钥匙的人调用,防止陌生人随便用、滥用大模型资源。
2. 基础了解
2.1 本地 API 服务的优势
- 解决云端痛点:云端大模型有隐私泄露风险、要付调用费、没网用不了,本地 API 服务完美规避这些问题。
- 适配多场景:医疗、金融等敏感行业,或无网络环境,都需要本地处理数据,不依赖外部服务。
- 降低使用门槛:封装后,不懂大模型底层的开发者,也能通过简单指令调用大模型能力。
2.2 FastAPI 是什么
- 轻量高效的 Python 框架:专门用来搭建 API 服务,比传统框架快很多,支持并发请求。
- 自带接口文档:自动生成接口文档(访问 /docs 就能看),不用手动写说明;语法简单,跟写普通 Python 函数差不多。
- 核心作用:把大模型的 "推理功能"(比如文本生成、问答),包装成 "可网络调用的接口"。
2.3 接口鉴权的核心目的
- 身份验证:确认调用者是 "自己人",不是恶意攻击者。
- 权限控制:防止大模型被滥用,比如频繁调用耗光资源。
- 常见鉴权方式:
- API Key:最常用的 "钥匙",一串唯一字符串,调用时带上即可。
- 基本认证:用 "用户名 + 密码" 做凭证,简单但安全性一般,需配合 HTTPS 使用。
- JWT 令牌:更灵活的 "临时钥匙",有过期时间,适合多场景权限管理。
三、核心原理
1. 大模型本地运行原理
前提: 本地设备(电脑/服务器)已安装大模型,如 Llama 2、Qwen 等开源模型,并能通过 Python 脚本运行。
核心: 模型加载到本地内存,通过代码调用其推理接口,生成结果,比如输入 "写一段文案",模型返回文案内容。
流程:

流程说明:
-
- 服务启动:FastAPI应用开始运行
-
- 状态检查:判断模型是否已经加载到内存中
-
- 模型加载:
- 已加载:直接复用现有模型实例,避免重复加载
- 未加载:按需加载模型,包含配置加载、分词器初始化、权重加载等步骤
-
- 单例模式:确保整个应用中只存在一个模型实例,减少内存占用
2. FastAPI 封装原理
- 加载大模型:启动服务时,把大模型加载到内存,避免每次调用都重新加载,提速。
- 定义接口函数:写一个 Python 函数,接收用户请求,比如提示词,调用大模型生成结果,再返回给用户。
- 启动服务:用 Uvicorn(ASGI 服务器)运行应用,大模型就变成了可网络访问的 API 服务。
3. 接口鉴权原理
3.1 调用 API Key 鉴权的接口
- 本质:验证 "调用者凭证" 的有效性。
- 通用流程:
-
- 服务器给合法用户发 "凭证",如 API Key。
-
- 用户调用 API 时,在请求中携带该凭证。
-
- 服务器接收请求后,先验证凭证是否正确,比如 API Key 是否存在、未过期,验证通过才让大模型处理请求。
-

核心流程:
-
- 客户端请求:客户端发起API请求,必须在HTTP请求头中包含X-API-Key字段
-
- 服务端接收:FastAPI服务接收请求,获取请求头中的API Key
-
- 密钥比对:从环境变量(.env文件)读取合法的API Key,与客户端提供的Key进行比对
-
- 认证决策:
- 认证失败:返回401未授权状态码,请求终止
- 认证成功:继续处理请求参数,调用大模型进行推理
3.2 调用 JWT 鉴权的接口
- 核心是"令牌申领-携带验证"两步走;
- 令牌携带需严格遵循"Bearer + 空格 + 令牌"格式,否则直接鉴权失败;
- 验证失败仅返回401错误,需重新申请令牌后再尝试调用。

核心流程:
-
- 客户端申请令牌:客户端向服务器的 /get-token 端点发送请求,通常需要提供身份凭证(如用户名和密码)。
-
- 服务器生成JWT令牌:服务器验证客户端提供的凭证,如果有效,则生成一个JWT令牌,并将其返回给客户端。
-
- 客户端携带令牌调用接口:客户端在后续的请求中,将得到的JWT令牌放在HTTP请求头的Authorization字段中,格式为Bearer 令牌,然后访问服务器上的业务接口。
-
- 服务器验证令牌有效性:服务器收到请求后,从Authorization头中提取令牌,并验证其签名和有效期。
-
- 验证结果处理:
- 如果令牌有效,服务器执行业务逻辑(例如,使用大模型生成文本)。
- 如果令牌无效(如签名错误、已过期等),则返回401错误。
-
- 返回业务结果或错误信息:服务器将业务逻辑处理的结果返回给客户端,或者在验证失败时返回错误信息。
四、JWT鉴权原理
1. JWT 的核心概念
JWT,JSON Web Token,JSON 格式的网络令牌,可以理解为:
服务器给客户端发的一串加密的"临时身份证",客户端后续调用接口时,带着这张"身份证",服务器验证"身份证"的真伪和有效期,就能确认身份。
2. JWT 的核心优势
- 无状态:对比session鉴权需要存会话,服务器不用存令牌信息,验证时只靠加密算法,适合本地 API 这种轻量部署场景;
- 过期可控:避免 API Key 一旦泄露就被永久滥用,大模型本地 API 的内存资源不会被无限占用;
- 轻量化:令牌是字符串,传输快,适配大模型 API 的低延迟需求。
3. JWT 的结构拆解
JWT 令牌由3 部分组成,用英文句号.分隔,比如实际的令牌:
bash
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJsb2NhbF9sbG1fdXNlciIsImV4cCI6MTcxNzc0MjQwMH0.8Z7k1X8s7a9L0b8K7j6H5g4F3d2S1a0Z9Y8X7W6V5U4T3S2R1Q0P
拆分成 3 部分:
- Header(头部):eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9,作用:声明加密算法 + 令牌类型 JWT_ALGORITHM = "HS256"
- Payload(载荷):eyJzdWIiOiJsb2NhbF9sbG1fdXNlciIsImV4cCI6MTcxNzc0MjQwMH0,作用:存储 "身份证信息"(如用户标识、过期时间)
- Signature(签名):8Z7k1X8s7a9L0b8K7j6H5g4F3d2S1a0Z9Y8X7W6V5U4T3S2R1Q0P,作用:加密校验(防止头部 / 载荷被篡改)
详细介绍:
1. Header(头部):告诉服务器怎么验证
- 本质:JSON 字符串,Base64 编码(不是加密,只是转格式);
- 内容为固定模板,jwt.encode会自动生成:
python
{
"alg": "HS256", // 加密算法(我们用的是对称加密HS256)
"typ": "JWT" // 令牌类型,固定为JWT
}
2. Payload(载荷):存储身份信息
- 本质:JSON 字符串,Base64 编码,可解码,不能存密码或密钥等敏感信息;
- 代码示例:
python
token_data = {
"sub": "local_llm_user", # 自定义的用户标识
"exp": datetime.utcnow() + timedelta(minutes=30) # 过期时间
}
3. Signature(签名):防止篡改的防伪码
- 核心作用:服务器用"密钥 + 算法"给 Header 和 Payload 加密,生成唯一签名;客户端篡改 Header/Payload 后,签名会失效,服务器能立刻发现。
- 加密公式:
bash
签名 = HMACSHA256(
Base64编码(Header) + "." + Base64编码(Payload),
服务器密钥(JWT_SECRET_KEY)
)
- 代码里的密钥:JWT_SECRET_KEY = "my_jwt_secret_123"
4. JWT 的核心原理
4.1 对称加密验证
- 服务器生成令牌和验证令牌,用的是同一把密钥(JWT_SECRET_KEY);
- 只要密钥不泄露,客户端无法伪造令牌(因为生成签名需要密钥);
- 注意:不要把密钥写在前端或客户端,只保留在服务器端(我们的代码里存在.env 或直接写在代码里,本地 API 没问题,生产环境建议用环境变量)。
4.2 无状态特性
- 服务器不用存"谁领了令牌""令牌是否有效",只靠加密算法验证;
- 对比传统的"session 鉴权",服务器要存 sessionID,JWT 更轻量,适合本地 API 这种简单部署场景。
4.3 过期机制
- Payload 里的exp字段是时间戳,服务器验证时会自动对比当前时间;
- 即使令牌泄露,攻击者也只能在过期前使用,风险可控(我们代码里设为 30 分钟,可按需调整)。
五、JWT 的完整工作流程
以我们的"本地大模型 API + 极简 JWT 鉴权"为例,流程分 4 步,每一步都对应代码里的接口函数:
1. 生成 JWT 令牌
生成JWT令牌,领临时身份证,对应接口:/get-token,对应函数:create_jwt_token()
执行逻辑:
-
- 客户端调用/get-token接口(比如浏览器访问http://127.0.0.1:8080/docs点击调用);
-
- 服务器执行create_jwt_token():
- 拼 Payload(用户标识 + 30 分钟过期时间);
- 用JWT_SECRET_KEY和 HS256 算法,把 Header+Payload 加密生成 Signature;
- 把 Header+Payload+Signature 用.拼接,生成完整 JWT 令牌;
-
- 服务器返回令牌给客户端(比如:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJsb2NhbF9sbG1fdXNlciIsImV4cCI6MTcxNzc0MjQwMH0.8Z7k1X8s7a9L0b8K7j6H5g4F3d2S1a0Z9Y8X7W6V5U4T3S2R1Q0P)。
代码核心片段:
python
def create_jwt_token():
token_data = {
"sub": "local_llm_user", # 身份标识
"exp": datetime.utcnow() + timedelta(minutes=30) # 过期时间
}
# 生成令牌:自动处理Header+Payload+Signature
token = jwt.encode(token_data, JWT_SECRET_KEY, algorithm=JWT_ALGORITHM)
return token
2. 客户端携带令牌调用接口
客户端携带令牌调用接口,即出示身份证,对应接口:/generate-text-jwt
执行逻辑:
-
- 客户端把令牌放在请求头里,格式固定为:Authorization: Bearer 令牌字符串;
比如:
- 客户端把令牌放在请求头里,格式固定为:Authorization: Bearer 令牌字符串;
bash
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJsb2NhbF9sbG1fdXNlciIsImV4cCI6MTcxNzc0MjQwMH0.8Z7k1X8s7a9L0b8K7j6H5g4F3d2S1a0Z9Y8X7W6V5U4T3S2R1Q0P
-
- 客户端发送请求到/generate-text-jwt,同时带上提示词(如 "写一段秋天的文案")。
3. 服务器验证令牌
检查身份证真伪,对应函数:verify_jwt_token()
执行逻辑:
-
- 服务器从请求头里提取令牌(credentials.credentials);
-
- 服务器用JWT_SECRET_KEY和 HS256 算法,做 3 件事:
-
- 拆分令牌为 Header/Payload/Signature;
-
- 重新计算签名:用本地密钥,对 Header+Payload 再次加密,生成 "新签名";
-
- 对比 "新签名" 和令牌里的 "旧签名":
- 不匹配→令牌被篡改(比如改了 Payload 里的过期时间),返回 401 错误;
- 匹配→继续校验过期时间;
-
- 校验 Payload 里的exp(过期时间):
- 已过期→返回 "令牌过期";
- 未过期→验证通过,提取用户标识(sub)。
代码核心片段:
python
def verify_jwt_token(credentials: HTTPAuthorizationCredentials = Depends(bearer_scheme)):
try:
token = credentials.credentials
# 解码+验证:自动校验签名+过期时间
payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=[JWT_ALGORITHM])
# 兜底检查过期时间(jwt库会自动校验,此处仅做提示)
expire = payload.get("exp")
if expire and datetime.utcfromtimestamp(expire) < datetime.utcnow():
raise HTTPException(status_code=401, detail="令牌已过期")
return payload.get("sub") # 返回用户标识
except JWTError: # 签名错误/篡改都会触发这个异常
raise HTTPException(status_code=401, detail="令牌无效")
4. 处理请求验证结果
- 验证通过→调用大模型生成文本,返回结果给客户端;
- 验证失败(令牌篡改 / 过期 / 无效)→返回 401 错误,提示 "重新获取令牌"。
5. 示例运行过程
5.1 基础库补充安装
python
# Windows
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-jose
# macOS/Linux
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple python-jose
5.2 示例启动
进入的文件所在目录,执行python main.py启动项目,出现以下界面表示项目启动成功:

5.3 获取 JWT 令牌
-
- 新建一个 POST 请求,URL 填 http://127.0.0.1:8080/get-token;
-
- 无需加请求头/请求体,直接点击 "Send";
-
- 复制返回结果中的access_token(示例:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJsb2NhbF9sbG1fdXNlciIsImV4cCI6MTc2NzQ0OTkyOX0.LlpxEytdkOwzNcNLi-SZwYwwEMg093sJ-oSNpFMNpfM)。

返回结果:
javascript
{
"code": 200,
"message": "令牌生成成功(有效期30分钟)",
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJsb2NhbF9sbG1fdXNlciIsImV4cCI6MTc2NzQ0OTkyOX0.LlpxEytdkOwzNcNLi-SZwYwwEMg093sJ-oSNpFMNpfM",
"token_type": "bearer"
}
5.4 调用 JWT 鉴权的生成接口
-
- 新建 POST 请求,URL 填 http://127.0.0.1:8080/generate-text-jwt;
-
- 切换到【Headers】标签页,新增 Authorization 请求头:
- Key:Authorization;
- Value:Bearer 复制的access_token(注意:Bearer 和令牌之间有一个空格!)

-
- 切换到【Body】标签页,填写和 API Key 方式相同的 JSON 请求体:

-
- 点击【Send】,即可返回生成结果。

返回结果:
{
"code": 200,
"message": "用户local_llm_user生成成功",
"data": {
"prompt": "写一段秋天的文案,温馨风格",
"result": "秋天,是一首诗意盎然的诗篇,它以金黄的稻谷、红艳的枫叶和丰收的果实,为大地披上了一层金色的纱衣。在这静谧的季节里,每一处都充满了生活的韵味。\n\n秋风轻轻吹过,带来了凉爽的气息,仿佛在诉说着岁月的故事。树叶开始变色,从绿色逐渐过渡到黄色、橙色和红色,宛如一幅色彩斑斓的油画。每一片叶子都在空中翩翩起舞,像是在向人们展示着它们的生命力和活力。这种景象让人感到宁静和平和,仿佛所有的烦恼和压力都被这美丽的景色所带走。\n\n秋天的天空也是另一番风景。蓝天如洗,云朵洁白无瑕,像棉花糖一样柔软而甜美。偶尔有几只小鸟飞过,欢快地鸣叫着,给这个安静的季节增添了生机与活力。阳光透过"
}
}
当我用一个错误的令牌测试,会直接提示"签名错误,解决:检查令牌是否正确,或重新获取"

5.5 接口请求记录
每一次失败或成功的接口请求都会有记录存在;

六、总结
JWT鉴权接口是本地大模型API中安全性更高的调用方式,核心依托"临时令牌"实现身份验证,适配多端访问、临时授权等场景,调用过程中需关注三大关键问题:一是令牌有效期,过期后需重新调用/get-token获取新令牌;二是令牌安全性,不可泄露给第三方,密钥需妥善保管;三是访问基础要求,需使用http://127.0.0.1:8080作为基础URL,确保服务正常启动且端口未被占用。
相较于API Key鉴权,JWT鉴权通过过期机制降低凭证泄露风险,更适合非固定场景的访问需求。掌握其调用逻辑,既能快速验证API功能完整性,也能为后续业务系统对接提供安全的鉴权参考,是本地大模型API落地应用的重要基础。
附录:完整的示例代码
python
# model_path = "D:\\modelscope\\hub\\qwen\\Qwen1___5-1___8B-Chat"
# 导入需要的库
from fastapi import FastAPI, Header, HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel, Field
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
from dotenv import load_dotenv
from jose import jwt, JWTError
from datetime import datetime, timedelta
import os
import uvicorn
# ====================== 第一步:加载配置(API Key+JWT配置) ======================
try:
load_dotenv()
# API Key配置
VALID_API_KEY = os.getenv("VALID_API_KEY", "default_key_123") # 无配置时用默认值
# JWT极简配置(新手不用改,理解即可)
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "my_jwt_secret_123") # 加密密钥
JWT_ALGORITHM = "HS256" # 加密算法(固定)
JWT_EXPIRE_MINUTES = 30 # 令牌过期时间(30分钟)
print("✅ 配置加载成功")
except Exception as e:
print(f"❌ 配置加载失败:{str(e)}")
exit(1)
# ====================== 第二步:单例加载模型(修复路径+内存优化) ======================
class LocalLLM:
_instance = None
_initialized = False
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if not LocalLLM._initialized:
# 修复1:用超轻量化模型(DistilGPT2),避免内存不足
# 先运行download_small_model.py下载模型到./model文件夹
model_path = "D:\\modelscope\\hub\\qwen\\Qwen1___5-1___8B-Chat" # 原始字符串避免反斜杠问题
try:
print("正在加载本地大模型...")
if not os.path.exists(model_path):
raise FileNotFoundError(
f"模型文件夹不存在:{model_path}\n解决:1. 运行download_small_model.py下载小模型;2. 确认路径正确")
# 修复2:添加low_cpu_mem_usage,减少内存占用
self.tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
self.model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.float32,
device_map="cpu",
trust_remote_code=True,
low_cpu_mem_usage=True # 减少CPU内存占用
)
self.model.eval()
LocalLLM._initialized = True
print("✅ 模型加载完成!")
except FileNotFoundError as e:
print(f"❌ 模型加载失败:{str(e)}")
exit(1)
except RuntimeError as e:
if "out of memory" in str(e).lower():
print(f"❌ 内存不足,请关闭其他程序(如浏览器/微信),或换更小的模型")
else:
print(f"❌ 模型运行错误:{str(e)}")
exit(1)
except Exception as e:
print(f"❌ 模型加载未知错误:{str(e)}")
exit(1)
def generate_text(self, prompt, max_length):
try:
if not prompt.strip():
raise ValueError("提示词不能为空")
inputs = self.tokenizer(prompt, return_tensors="pt", truncation=True, max_length=512)
if inputs.input_ids.shape[1] > 512:
raise ValueError(f"提示词过长({inputs.input_ids.shape[1]}token),最大支持512token")
with torch.no_grad():
outputs = self.model.generate(**inputs, max_length=max_length, temperature=0.7, pad_token_id=self.tokenizer.eos_token_id)
result = self.tokenizer.decode(outputs[0], skip_special_tokens=True).replace(prompt, "").strip()
if not result:
raise ValueError("模型未生成内容,请换提示词")
return result
except ValueError as e:
raise HTTPException(status_code=400, detail=f"参数错误:{str(e)}")
except Exception as e:
raise HTTPException(status_code=500, detail=f"推理错误:{str(e)}")
# 创建模型实例
try:
llm = LocalLLM()
except Exception as e:
print(f"❌ 模型初始化失败:{str(e)}")
exit(1)
# ====================== 第三步:极简JWT鉴权核心函数 ======================
bearer_scheme = HTTPBearer()
def create_jwt_token():
"""生成JWT令牌(简化版:无用户名密码,直接生成)"""
try:
token_data = {
"sub": "local_llm_user",
"exp": datetime.utcnow() + timedelta(minutes=JWT_EXPIRE_MINUTES)
}
token = jwt.encode(token_data, JWT_SECRET_KEY, algorithm=JWT_ALGORITHM)
return token
except Exception as e:
raise HTTPException(status_code=500, detail=f"生成令牌失败:{str(e)}")
def verify_jwt_token(credentials: HTTPAuthorizationCredentials = Depends(bearer_scheme)):
"""验证JWT令牌(简化版:只检查有效性和过期时间)"""
try:
token = credentials.credentials
payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=[JWT_ALGORITHM])
expire = payload.get("exp")
if expire and datetime.utcfromtimestamp(expire) < datetime.utcnow():
raise HTTPException(status_code=401, detail="❌ JWT令牌已过期\n解决:重新调用/get-token获取新令牌")
return payload.get("sub")
except JWTError as e:
raise HTTPException(status_code=401, detail=f"❌ JWT令牌无效/签名错误\n解决:检查令牌是否正确,或重新获取")
except Exception as e:
raise HTTPException(status_code=401, detail=f"❌ 令牌验证失败:{str(e)}")
# ====================== 第四步:FastAPI接口(API Key+JWT双鉴权) ======================
app = FastAPI(title="本地大模型API(API Key+极简JWT鉴权)")
# 请求体模型(保留)
class LLMRequest(BaseModel):
prompt: str = Field(..., description="提示词", max_length=500)
max_length: int = Field(100, description="生成长度", ge=10, le=1000)
# 接口1:获取JWT令牌
@app.post("/get-token", summary="获取JWT令牌(无需密码,直接领)")
def get_jwt_token():
token = create_jwt_token()
return {
"code": 200,
"message": "令牌生成成功(有效期30分钟)",
"access_token": token,
"token_type": "bearer"
}
# 接口2:API Key鉴权的生成接口
@app.post("/generate-text-apikey", summary="API Key鉴权-文本生成")
def generate_by_apikey(request: LLMRequest, x_api_key: str = Header(None)):
try:
if not x_api_key:
raise HTTPException(status_code=401, detail="❌ 请传入X-API-Key")
if x_api_key.strip() != VALID_API_KEY:
raise HTTPException(status_code=401, detail="❌ API Key错误")
except HTTPException as e:
raise e
try:
result = llm.generate_text(request.prompt, request.max_length)
return {"code": 200, "message": "生成成功", "data": {"prompt": request.prompt, "result": result}}
except HTTPException as e:
raise e
# 接口3:JWT鉴权的生成接口
@app.post("/generate-text-jwt", summary="JWT鉴权-文本生成")
def generate_by_jwt(
request: LLMRequest,
username: str = Depends(verify_jwt_token)
):
try:
result = llm.generate_text(request.prompt, request.max_length)
return {
"code": 200,
"message": f"用户{username}生成成功",
"data": {"prompt": request.prompt, "result": result}
}
except HTTPException as e:
raise e
# ====================== 第五步:启动服务(修复端口+日志) ======================
if __name__ == "__main__":
try:
# 修复3:改端口为8080(避免8000被占用),添加更多日志
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8080, # 改端口,避免占用
reload=False,
log_level="debug",
access_log=True # 开启访问日志,便于排查
)
except OSError as e:
if "address already in use" in str(e).lower():
print(f"❌ 服务启动失败:端口8080被占用\n解决:1. 改端口为8090;2. 结束占用8080的程序")
else:
print(f"❌ 服务启动失败:{str(e)}")
exit(1)
except Exception as e:
print(f"❌ 服务启动失败:{str(e)}\n解决:检查Python依赖是否安装完整")
exit(1)