大模型应用:大模型的本地 API 服务:FastAPI 封装与接口鉴权.44

一、引言

大模型的里里外外我们都进行了很多细节的讲解,但大模型的部署引用还没有涉及太多,今天我们重点讲一下模型的接口发布,以及利用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 脚本运行。
核心: 模型加载到本地内存,通过代码调用其推理接口,生成结果,比如输入 "写一段文案",模型返回文案内容。
流程:

流程说明:

    1. 服务启动:FastAPI应用开始运行
    1. 状态检查:判断模型是否已经加载到内存中
    1. 模型加载:
    • 已加载:直接复用现有模型实例,避免重复加载
    • 未加载:按需加载模型,包含配置加载、分词器初始化、权重加载等步骤
    1. 单例模式:确保整个应用中只存在一个模型实例,减少内存占用

2. FastAPI 封装原理

  • 加载大模型:启动服务时,把大模型加载到内存,避免每次调用都重新加载,提速。
  • 定义接口函数:写一个 Python 函数,接收用户请求,比如提示词,调用大模型生成结果,再返回给用户。
  • 启动服务:用 Uvicorn(ASGI 服务器)运行应用,大模型就变成了可网络访问的 API 服务。

3. 接口鉴权原理

3.1 调用 API Key 鉴权的接口

  • 本质:验证 "调用者凭证" 的有效性。
  • 通用流程:
      1. 服务器给合法用户发 "凭证",如 API Key。
      1. 用户调用 API 时,在请求中携带该凭证。
      1. 服务器接收请求后,先验证凭证是否正确,比如 API Key 是否存在、未过期,验证通过才让大模型处理请求。

核心流程:

    1. 客户端请求:客户端发起API请求,必须在HTTP请求头中包含X-API-Key字段
    1. 服务端接收:FastAPI服务接收请求,获取请求头中的API Key
    1. 密钥比对:从环境变量(.env文件)读取合法的API Key,与客户端提供的Key进行比对
    1. 认证决策:
    • 认证失败:返回401未授权状态码,请求终止
    • 认证成功:继续处理请求参数,调用大模型进行推理

3.2 调用 JWT 鉴权的接口

  • 核心是"令牌申领-携带验证"两步走;
  • 令牌携带需严格遵循"Bearer + 空格 + 令牌"格式,否则直接鉴权失败;
  • 验证失败仅返回401错误,需重新申请令牌后再尝试调用。

核心流程:

    1. 客户端申请令牌:客户端向服务器的 /get-token 端点发送请求,通常需要提供身份凭证(如用户名和密码)。
    1. 服务器生成JWT令牌:服务器验证客户端提供的凭证,如果有效,则生成一个JWT令牌,并将其返回给客户端。
    1. 客户端携带令牌调用接口:客户端在后续的请求中,将得到的JWT令牌放在HTTP请求头的Authorization字段中,格式为Bearer 令牌,然后访问服务器上的业务接口。
    1. 服务器验证令牌有效性:服务器收到请求后,从Authorization头中提取令牌,并验证其签名和有效期。
    1. 验证结果处理:
    • 如果令牌有效,服务器执行业务逻辑(例如,使用大模型生成文本)。
    • 如果令牌无效(如签名错误、已过期等),则返回401错误。
    1. 返回业务结果或错误信息:服务器将业务逻辑处理的结果返回给客户端,或者在验证失败时返回错误信息。

四、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()

执行逻辑:

    1. 客户端调用/get-token接口(比如浏览器访问http://127.0.0.1:8080/docs点击调用);
    1. 服务器执行create_jwt_token():
    • 拼 Payload(用户标识 + 30 分钟过期时间);
    • 用JWT_SECRET_KEY和 HS256 算法,把 Header+Payload 加密生成 Signature;
    • 把 Header+Payload+Signature 用.拼接,生成完整 JWT 令牌;
    1. 服务器返回令牌给客户端(比如: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

执行逻辑:

    1. 客户端把令牌放在请求头里,格式固定为:Authorization: Bearer 令牌字符串;
      比如:
bash 复制代码
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJsb2NhbF9sbG1fdXNlciIsImV4cCI6MTcxNzc0MjQwMH0.8Z7k1X8s7a9L0b8K7j6H5g4F3d2S1a0Z9Y8X7W6V5U4T3S2R1Q0P
    1. 客户端发送请求到/generate-text-jwt,同时带上提示词(如 "写一段秋天的文案")。

3. 服务器验证令牌

检查身份证真伪,对应函数:verify_jwt_token()

执行逻辑:

    1. 服务器从请求头里提取令牌(credentials.credentials);
    1. 服务器用JWT_SECRET_KEY和 HS256 算法,做 3 件事:
      1. 拆分令牌为 Header/Payload/Signature;
      1. 重新计算签名:用本地密钥,对 Header+Payload 再次加密,生成 "新签名";
      1. 对比 "新签名" 和令牌里的 "旧签名":
      • 不匹配→令牌被篡改(比如改了 Payload 里的过期时间),返回 401 错误;
      • 匹配→继续校验过期时间;
    1. 校验 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 令牌

    1. 新建一个 POST 请求,URL 填 http://127.0.0.1:8080/get-token;
    1. 无需加请求头/请求体,直接点击 "Send";
    1. 复制返回结果中的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 鉴权的生成接口

    1. 新建 POST 请求,URL 填 http://127.0.0.1:8080/generate-text-jwt;
    1. 切换到【Headers】标签页,新增 Authorization 请求头:
    • Key:Authorization;
    • Value:Bearer 复制的access_token(注意:Bearer 和令牌之间有一个空格!)
    1. 切换到【Body】标签页,填写和 API Key 方式相同的 JSON 请求体:
    1. 点击【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)
相关推荐
杰瑞哥哥13 小时前
快速搭建Web前端(streamlit使用指南)
python·信息可视化·web·模型部署
laufing13 小时前
sqlmodel -- fastapi 连接关系型数据库
数据库·fastapi·sqlmodel
PieroPc14 小时前
用FastAPI 后端 和 HTML/CSS/JavaScript 前端写一个博客系统 例
前端·html·fastapi
bst@微胖子14 小时前
CrewAI+FastAPI的Pipelines功能实现多CrewAI工作流以及Flows功能实现复杂工作流
服务器·windows·fastapi
山沐与山14 小时前
【FastAPI】FastAPI RESTful API实战:从接口规范到优雅设计
后端·restful·fastapi
minhuan14 小时前
大模型应用:本地大模型API调用鉴权可视化全解析:从基础实现到业务扩展.45
api调用·大模型应用·大模型本地部署·jwt鉴权
哈里谢顿1 天前
事件循环介绍
fastapi
知行学思1 天前
Python配置管理完全指南:从dotenv到pydantic_settings
数据库·python·fastapi·环境变量·配置管理·pydantic·dotenv
哈里谢顿1 天前
FastAPI 从 0 到 1:史上最良心的现代 Python Web 框架入门指南
fastapi