资讯动态

FastAPI与LLM集成实战:三天构建AI对话Web服务

发布时间:2026/8/21 23:26:55 来源:尧图企业网站定制
最近在尝试将大语言模型LLM集成到自己的Web应用中时发现很多教程要么只讲FastAPI要么只讲LLM调用两者结合且能直接上手的实战案例很少。要么环境配置复杂要么代码片段零散对于想快速构建一个可交互AI服务的开发者来说门槛不低。本文旨在解决这个问题提供一个从零开始的完整路径。我们将用三天时间系统学习FastAPI框架并最终用它搭建一个具备基础LLM对话能力的Web服务。整个过程会涵盖环境搭建、核心语法、项目结构设计、LLM接口集成以及关键的Prompt工程基础确保每一步都有可运行的代码和清晰的解释。无论你是想为现有项目添加AI能力还是希望快速入门AI应用开发这篇指南都能提供一条清晰的实践路线。1. 背景与核心概念为什么是FastAPI LLM在开始动手之前我们需要理解为什么这个技术组合在当前如此流行以及它能解决什么问题。1.1 FastAPI现代Python Web框架的佼佼者FastAPI是一个用于构建API的现代、快速高性能的Web框架基于标准Python类型提示。它的核心优势在于高性能得益于Starlette用于Web处理和Pydantic用于数据验证其性能可与NodeJS和Go比肩。快速开发自动化的交互式API文档Swagger UI和ReDoc、强大的编辑器支持类型检查、自动补全极大地提升了开发效率。易于学习如果你熟悉Python的类型提示那么上手FastAPI会非常自然。对于LLM应用开发FastAPI的异步支持async/await至关重要。因为调用外部LLM API如OpenAI、文心一言等通常是网络I/O密集型操作使用异步可以避免阻塞显著提升服务的并发处理能力。1.2 LLM与Prompt工程基础大语言模型LLM是一种基于海量文本数据训练出的、能够理解和生成自然语言的深度学习模型。我们通常不直接“运行”一个庞大的模型而是通过API调用云端服务如OpenAI的GPT系列、国内的通义千问等或在本地部署开源模型如ChatGLM、Llama等来使用其能力。与LLM交互的核心是Prompt提示词。你可以把它理解为给模型的“指令”或“问题”。Prompt的质量直接决定了模型输出的效果。Prompt Engineering提示工程就是设计和优化这些提示词以引导模型产生更准确、更相关、更符合格式要求的回答的一门艺术。例如一个简单的分类任务好的Prompt会明确告诉模型“请将以下文本分类为‘正面’、‘负面’或‘中性’情感。只输出一个词。”1.3 结合场景构建AI服务后端将FastAPI与LLM结合典型的应用场景包括智能客服/聊天机器人提供Web API接口接收用户问题调用LLM生成回答。内容生成助手根据用户输入的关键词或大纲生成文章、邮件、代码等。数据提取与格式化从非结构化文本如合同、报告中提取特定信息并格式化为JSON。代码解释与生成接受自然语言描述生成或解释代码片段。FastAPI负责处理HTTP请求、用户认证、数据验证和返回响应而LLM则作为核心的“大脑”处理复杂的语言理解和生成任务。接下来我们就从环境搭建开始一步步实现这个组合。2. 环境准备与版本说明为了确保示例代码能够顺利运行请先准备好以下环境。本文示例将在常见环境下进行重点在于演示思路和核心代码你可以根据自己项目的实际情况调整版本。2.1 基础环境操作系统Windows 10/11, macOS, 或 Linux (如 Ubuntu 20.04)。Python版本Python 3.8。强烈建议使用Python 3.10或更高版本以获得更好的类型提示支持。可以使用python --version检查。包管理工具pip。建议使用虚拟环境venv或conda来隔离项目依赖。2.2 创建项目与虚拟环境首先创建一个项目目录并进入。mkdir fastapi-llm-demo cd fastapi-llm-demo在项目根目录下创建Python虚拟环境。# Windows python -m venv venv venv\Scripts\activate # macOS/Linux python3 -m venv venv source venv/bin/activate激活后命令行提示符前通常会显示(venv)表示已进入虚拟环境。2.3 安装核心依赖我们将安装FastAPI、用于运行服务器的Uvicorn以及用于调用LLM API的openai库这里以OpenAI API为例其他厂商SDK类似。创建一个requirements.txt文件。fastapi0.104.1 uvicorn[standard]0.24.0 openai0.28.0 pydantic2.5.0 python-dotenv1.0.0使用pip安装pip install -r requirements.txt关键版本说明fastapi和uvicorn版本保持较新即可它们之间兼容性很好。openai库的版本需要注意其接口在v1.0前后有较大变化。本文使用较稳定的0.28.0版本。如果你使用更新的v1.x版本代码调用方式需要调整主要涉及客户端初始化。python-dotenv用于从.env文件加载环境变量如API密钥避免将敏感信息硬编码在代码中。2.4 项目结构预览在开始编码前我们先规划一个清晰的项目结构这对于后续维护和功能扩展很有帮助。fastapi-llm-demo/ ├── .env # 存储环境变量如API密钥需加入.gitignore ├── .gitignore ├── requirements.txt # 项目依赖 ├── main.py # FastAPI应用主入口 ├── config.py # 配置文件 ├── routers/ # 路由模块目录 │ ├── __init__.py │ └── chat.py # 聊天相关的路由 ├── services/ # 业务逻辑服务层 │ ├── __init__.py │ └── llm_service.py # LLM调用封装 └── schemas/ # Pydantic数据模型定义 ├── __init__.py └── chat.py # 聊天请求/响应模型这个结构遵循了关注点分离的原则让代码更易读、易测试。3. FastAPI核心语法与配置拆解在构建完整应用前我们需要快速掌握FastAPI的几个核心概念和语法。3.1 最小的FastAPI应用创建一个main.py文件写入以下代码# main.py from fastapi import FastAPI import uvicorn # 创建FastAPI应用实例 app FastAPI(titleLLM API Demo, description一个简单的LLM服务演示) # 定义一个根路径的GET请求处理函数路由 app.get(/) async def read_root(): return {message: Hello, FastAPI with LLM!} # 运行服务器仅在直接运行此脚本时执行 if __name__ __main__: uvicorn.run(app, host0.0.0.0, port8000)代码解释FastAPI()实例化应用可以传入标题、描述等元信息这些会自动显示在API文档中。app.get(“/“)这是一个路径操作装饰器。它告诉FastAPI下面的函数read_root负责处理发送到根路径/的GET请求。async def将函数定义为异步函数。对于I/O操作如调用LLM API使用异步可以提升性能。uvicorn.run(...)使用Uvicorn ASGI服务器运行应用。host”0.0.0.0″表示监听所有网络接口port8000指定端口。运行它python main.py访问http://127.0.0.1:8000你会看到JSON响应{“message”: “Hello, FastAPI with LLM!”}。更强大的是访问http://127.0.0.1:8000/docs你会看到自动生成的交互式API文档Swagger UI。3.2 路径参数、查询参数与请求体与LLM交互通常需要接收用户输入FastAPI提供了简洁的方式来声明这些参数。路径参数从URL路径中获取。app.get(/items/{item_id}) async def read_item(item_id: int): # 类型提示会自动转换为int并验证 return {item_id: item_id}访问/items/42返回{“item_id”: 42}。查询参数从URL的?后获取。app.get(/chat/) async def chat_with_llm(message: str, max_tokens: int 100): # 假设这里调用LLM simulated_response fEcho: {message} (max_tokens: {max_tokens}) return {response: simulated_response}访问/chat/?message你好max_tokens50返回{“response”: “Echo: 你好 (max_tokens: 50)”}。max_tokens有默认值是可选的。请求体POST用于接收客户端发送的JSON数据。这里需要用到Pydantic模型。 首先在schemas/chat.py中定义数据模型# schemas/chat.py from pydantic import BaseModel class ChatRequest(BaseModel): message: str max_tokens: int 200 temperature: float 0.7 # 控制生成随机性的参数 class ChatResponse(BaseModel): response: str tokens_used: int然后在路由中使用它# routers/chat.py from fastapi import APIRouter from schemas.chat import ChatRequest, ChatResponse router APIRouter(prefix/api/v1, tags[chat]) router.post(/chat, response_modelChatResponse) async def create_chat_completion(request: ChatRequest): # request.message, request.max_tokens 等可直接使用 # 这里先模拟LLM调用 simulated_response f模拟LLM对 ‘{request.message}’ 的回复 return ChatResponse(responsesimulated_response, tokens_used50)关键点APIRouter用于组织路由prefix为所有路由添加前缀tags用于在API文档中分组。response_modelChatResponse指定响应数据的模型FastAPI会自动将返回值转换为JSON并验证其结构。request: ChatRequest声明请求体参数。FastAPI会解析请求中的JSON并验证其是否符合ChatRequest模型的定义类型错误或缺失必填字段会自动返回422错误。3.3 依赖注入与配置管理依赖注入Dependency Injection是FastAPI的超级功能之一它使得管理共享逻辑如数据库会话、认证、配置变得非常容易。我们将API密钥和LLM客户端配置化。首先创建.env文件切记不要提交到Git# .env OPENAI_API_KEYyour_openai_api_key_here OPENAI_BASE_URLhttps://api.openai.com/v1 # 如果使用其他兼容API可修改 MODEL_NAMEgpt-3.5-turbo然后创建config.py来读取配置# config.py from pydantic_settings import BaseSettings # 注意需要安装 pydantic-settings class Settings(BaseSettings): openai_api_key: str openai_base_url: str https://api.openai.com/v1 model_name: str gpt-3.5-turbo class Config: env_file .env settings Settings()注意pydantic-settings是Pydantic v2的扩展用于更优雅地处理设置。你需要先安装pip install pydantic-settings。或者你也可以使用python-dotenv结合普通Pydantic模型手动加载。接着创建一个依赖项用于在需要的地方注入LLM客户端# services/llm_service.py import openai from config import settings # 配置OpenAI客户端v0.28.0版本方式 openai.api_key settings.openai_api_key openai.api_base settings.openai_base_url async def get_llm_client(): # 这里返回配置好的客户端对于更复杂的场景可以在这里初始化不同的LLM客户端 # 目前openai库是全局配置所以直接返回库本身或一个标识即可 # 如果是v1.x客户端则需要在这里实例化并返回 client return openai现在我们可以在路由中通过依赖注入使用它。4. 完整实战案例构建LLM聊天API服务现在我们将把所有部分组合起来构建一个完整的、可配置的LLM聊天API服务。4.1 整合项目结构并编写核心服务首先确保你的项目结构如之前所述。然后编写LLM服务层services/llm_service.py# services/llm_service.py import openai from typing import Optional from config import settings from schemas.chat import ChatRequest class LLMService: def __init__(self): # 初始化配置v0.28.0方式 openai.api_key settings.openai_api_key if settings.openai_base_url: openai.api_base settings.openai_base_url self.model settings.model_name async def generate_chat_response(self, request: ChatRequest) - dict: 调用OpenAI Chat Completion API生成回复。 返回包含回复文本和token使用量的字典。 try: response await openai.ChatCompletion.acreate( modelself.model, messages[ {role: system, content: 你是一个有帮助的助手。}, {role: user, content: request.message} ], max_tokensrequest.max_tokens, temperaturerequest.temperature, # streamTrue # 如果需要流式响应可以启用 ) # 解析响应 reply response.choices[0].message.content tokens_used response.usage.total_tokens return { response: reply, tokens_used: tokens_used } except openai.error.AuthenticationError: return {error: API密钥无效或缺失。} except openai.error.RateLimitError: return {error: 达到API速率限制请稍后再试。} except Exception as e: return {error: f调用LLM服务时发生错误: {str(e)}} # 创建全局服务实例简单起见也可用依赖注入管理生命周期 llm_service LLMService()代码要点将配置集中管理。使用async/await调用OpenAI的异步APIacreate避免阻塞事件循环。在messages参数中我们构建了一个简单的对话上下文system消息设定助手角色user消息是用户的输入。这是Prompt工程最基础的实践。包含了基本的错误处理返回友好的错误信息。4.2 编写路由并集成服务更新routers/chat.py# routers/chat.py from fastapi import APIRouter, HTTPException from schemas.chat import ChatRequest, ChatResponse from services.llm_service import llm_service router APIRouter(prefix/api/v1, tags[Chat]) router.post(/chat, response_modelChatResponse, summary与LLM对话) async def chat_completion(request: ChatRequest): 发送一条消息给LLM并获取回复。 - **message**: 用户输入的消息文本 - **max_tokens**: 回复的最大token数默认200 - **temperature**: 生成随机性越高越随机默认0.7 result await llm_service.generate_chat_response(request) if error in result: # 如果服务层返回错误抛出HTTP异常 raise HTTPException(status_code500, detailresult[error]) # 将结果适配到响应模型 return ChatResponse( responseresult[response], tokens_usedresult[tokens_used] )代码要点使用APIRouter组织路由prefix和tags让API文档更清晰。函数文档字符串会自动显示在API文档中。调用llm_service并处理其返回的错误。使用HTTPException返回标准化的错误响应。4.3 更新主应用文件更新main.py导入并包含我们创建的路由器。# main.py from fastapi import FastAPI from routers import chat import uvicorn app FastAPI( titleLLM Chat API Service, description一个基于FastAPI和OpenAI API构建的聊天服务演示, version1.0.0 ) # 包含路由 app.include_router(chat.router) app.get(/) async def root(): return {message: 欢迎使用LLM Chat API服务请访问 /docs 查看接口文档。} if __name__ __main__: uvicorn.run(main:app, host0.0.0.0, port8000, reloadTrue)关键改动app.include_router(chat.router)将chat路由器挂载到主应用上。uvicorn.run(“main:app”, … reloadTrue)这里使用了模块字符串”main:app”的写法并且开启了reload模式这样在开发时修改代码服务器会自动重启非常方便。4.4 运行与验证启动服务在项目根目录下运行python main.py。你应该看到Uvicorn启动的日志。测试API打开浏览器访问http://127.0.0.1:8000/docs。你会看到自动生成的Swagger UI界面其中包含了/api/v1/chat这个POST接口。点击 “Try it out” 按钮。在请求体JSON中填入{ message: 请用Python写一个快速排序函数, max_tokens: 300, temperature: 0.5 }点击 “Execute”。如果API密钥配置正确你将看到来自LLM的代码回复以及接口返回的response和tokens_used。至此一个基础的、可工作的LLM聊天服务后端就搭建完成了。它具备了清晰的架构、配置管理、错误处理和完整的API文档。5. Prompt工程基础与进阶实践仅仅能调用API还不够要让LLM发挥出最佳效果我们需要设计好的Prompt。本节将结合我们的服务介绍几种实用的Prompt模式。5.1 系统提示词System Prompt的威力在上面的例子中我们使用了固定的系统提示词”你是一个有帮助的助手。”。这只是一个最简单的例子。系统提示词用于在对话开始前为模型设定角色、规则和上下文。进阶示例让我们修改服务支持自定义系统提示词。 首先更新数据模型schemas/chat.py# schemas/chat.py from pydantic import BaseModel, Field class ChatRequest(BaseModel): message: str system_prompt: str Field( default你是一个专业、准确且乐于助人的AI助手。, description设定助手行为的系统提示词 ) max_tokens: int Field(default200, ge1, le4000, description生成回复的最大token数) temperature: float Field(default0.7, ge0.0, le2.0, description生成随机性0为确定性最高)然后更新LLMService中的generate_chat_response方法async def generate_chat_response(self, request: ChatRequest) - dict: try: response await openai.ChatCompletion.acreate( modelself.model, messages[ {role: system, content: request.system_prompt}, # 使用传入的系统提示词 {role: user, content: request.message} ], max_tokensrequest.max_tokens, temperaturerequest.temperature, ) # ... 解析响应 ...现在你可以通过API指定不同的系统角色例如”你是一位经验丰富的软件架构师请用简洁的语言解释微服务。””你是一位严格的代码审查员请找出以下代码中的问题并给出修改建议。”5.2 上下文管理多轮对话真实的聊天往往是多轮的。我们需要维护一个对话历史列表。这需要在服务层或数据库层面进行状态管理。这里展示一个基于内存的简单会话管理。在services/llm_service.py中新增一个类和方法# services/llm_service.py (新增部分) from collections import defaultdict from typing import List, Dict class ChatSessionManager: def __init__(self): # 使用字典在内存中存储会话key为session_idvalue为消息列表 self.sessions: Dict[str, List[Dict]] defaultdict(list) def create_session(self, session_id: str, system_prompt: str None): 创建一个新的会话并初始化系统消息 if session_id in self.sessions: self.clear_session(session_id) initial_messages [] if system_prompt: initial_messages.append({role: system, content: system_prompt}) self.sessions[session_id] initial_messages return session_id def add_user_message(self, session_id: str, content: str): 向会话中添加用户消息 if session_id not in self.sessions: self.create_session(session_id) self.sessions[session_id].append({role: user, content: content}) def add_assistant_message(self, session_id: str, content: str): 向会话中添加助手消息用于存储历史回复 self.sessions[session_id].append({role: assistant, content: content}) def get_messages(self, session_id: str) - List[Dict]: 获取会话的完整消息历史 return self.sessions.get(session_id, []) def clear_session(self, session_id: str): 清空指定会话的历史 if session_id in self.sessions: self.sessions[session_id].clear() # 全局会话管理器实例 session_manager ChatSessionManager()然后创建新的路由来处理带上下文的聊天# routers/chat.py (新增路由) from schemas.chat import ChatRequest, ChatResponse, ChatSessionRequest from services.llm_service import llm_service, session_manager class ChatSessionRequest(BaseModel): session_id: str Field(..., description会话ID用于维持多轮对话上下文) message: str system_prompt: str Field(default你是一个有帮助的助手。) router.post(/chat/session, response_modelChatResponse) async def chat_with_session(request: ChatSessionRequest): # 1. 获取或创建会话并添加用户新消息 current_messages session_manager.get_messages(request.session_id) if not current_messages and request.system_prompt: # 如果是新会话初始化系统消息 session_manager.create_session(request.session_id, request.system_prompt) session_manager.add_user_message(request.session_id, request.message) # 2. 获取当前会话的完整历史消息 messages_for_llm session_manager.get_messages(request.session_id) # 3. 调用LLM这里简化直接使用原有服务需调整服务方法以接收消息列表 # 假设我们修改了 llm_service.generate_chat_response 以接收 messages 参数 result await llm_service.generate_chat_response_with_messages(messages_for_llm, max_tokens200) if error in result: raise HTTPException(status_code500, detailresult[error]) # 4. 将LLM的回复也加入到会话历史中 session_manager.add_assistant_message(request.session_id, result[response]) return ChatResponse(responseresult[response], tokens_usedresult[tokens_used])注意这只是一个内存中的简单实现。在生产环境中你需要考虑会话存储使用数据库如Redis、PostgreSQL来持久化会话以支持重启和分布式部署。上下文窗口限制LLM有token数量限制。需要实现一个策略当历史消息总token数超过限制时进行截断或总结。会话过期与清理定期清理不活跃的会话释放资源。5.3 结构化输出与函数调用很多时候我们希望LLM的输出不是一段自由文本而是结构化的数据如JSON以便程序后续处理。OpenAI的Chat Completion API支持通过function calling或JSON modegpt-4-1106-preview及更高版本来引导模型输出结构化内容。例如我们希望LLM从一段用户描述中提取事件信息。我们可以这样设计Prompt和调用# 在services/llm_service.py中新增一个方法 async def extract_event_info(self, user_description: str) - dict: functions [ { name: extract_event_details, description: 从文本中提取事件详情, parameters: { type: object, properties: { event_name: {type: string, description: 事件名称}, date: {type: string, description: 事件日期格式YYYY-MM-DD}, location: {type: string, description: 事件地点}, attendees: { type: array, items: {type: string}, description: 参与者名单 } }, required: [event_name, date] } } ] try: response await openai.ChatCompletion.acreate( modelself.model, messages[{role: user, content: user_description}], functionsfunctions, function_call{name: extract_event_details} # 强制调用特定函数 ) # 解析返回的函数调用参数 import json arguments response.choices[0].message.get(function_call, {}).get(arguments) if arguments: return json.loads(arguments) else: return {error: 未能提取结构化信息} except Exception as e: return {error: f提取失败: {str(e)}}然后为这个功能创建一个新的路由。这样前端发送一段文本”下周一下午三点我和张三、李四在会议室开会讨论项目启动。”后端就能返回一个结构化的JSON对象包含事件名、日期、地点和参与者。6. 常见问题与排查思路在开发和部署过程中你可能会遇到以下问题。这里提供一个排查指南。问题现象可能原因解决思路启动服务时报ModuleNotFoundError依赖未安装或虚拟环境未激活。1. 确认已激活虚拟环境(venv)。2. 运行pip install -r requirements.txt确保所有依赖已安装。访问localhost:8000/docs无响应或404服务未成功启动或路由未正确挂载。1. 检查终端是否有Uvicorn启动成功的日志。2. 检查main.py中app.include_router是否正确。3. 尝试直接访问localhost:8000看根路径是否响应。调用/api/v1/chat返回422 Unprocessable Entity请求体数据不符合Pydantic模型定义。1. 检查API文档中的请求体格式确保字段名和类型正确。2. 检查是否有必填字段未提供。3. 使用print(request.dict())在路由函数内打印接收到的数据调试。调用LLM API返回401或AuthenticationErrorAPI密钥错误、过期或未设置。1. 检查.env文件中的OPENAI_API_KEY是否正确。2. 确保.env文件位于项目根目录且已被正确加载。3. 在代码中打印settings.openai_api_key的前几位确认已读取。调用LLM API超时或响应慢网络问题或LLM服务提供商响应慢。1. 增加FastAPI和HTTP客户端的超时设置。2. 考虑在调用LLM API时使用异步并设置合理的超时。3. 检查本地网络连接。多轮对话时后续回复似乎忘记了之前的对话会话历史未正确传递给LLM。1. 检查session_manager.get_messages返回的消息列表是否正确包含了历史记录。2. 确认调用LLM API时messages参数传递的是完整的对话历史列表。提示词效果不佳回复不准确或冗长Prompt设计不够明确。1. 优化系统提示词更精确地定义角色和任务。2. 在用户消息中提供更具体的指令和示例Few-shot Prompting。3. 调整temperature和max_tokens参数。关于422 Unprocessable Entity的深度排查 这是一个非常常见的FastAPI错误意味着请求数据验证失败。除了检查字段还需注意数据类型确保JSON中的数字没有用引号包成字符串除非模型字段是str。默认值如果字段有默认值不传该字段是允许的。Pydantic严格模式默认情况下Pydantic会尝试进行类型转换如字符串”123″转整数123。如果希望严格匹配可以在字段上使用strictTrue参数。7. 最佳实践与工程建议将学习项目转化为可维护、可扩展的生产级服务需要注意以下方面。7.1 配置与安全永远不要硬编码密钥始终使用环境变量或配置文件。.env文件必须加入.gitignore。使用配置管理库如pydantic-settings它支持从多种来源环境变量、.env文件、密钥管理服务加载配置并自动验证。API密钥轮换制定计划定期轮换API密钥并在服务中实现无缝切换。限制访问在生产环境中使用反向代理如Nginx配置IP白名单、速率限制并使用HTTPS。7.2 错误处理与日志全局异常处理器在FastAPI中可以使用app.exception_handler来定义全局的异常处理逻辑返回统一的错误格式。from fastapi import FastAPI, Request from fastapi.responses import JSONResponse app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): # 记录详细的错误日志到文件或监控系统 logger.error(f全局异常: {exc}, exc_infoTrue) # 对客户端返回友好的错误信息避免泄露内部细节 return JSONResponse( status_code500, content{detail: 服务器内部错误请稍后重试。} )结构化日志使用logging模块或structlog库记录结构化的日志便于后续查询和分析。记录关键信息请求ID、用户标识、LLM调用参数、token使用量、响应时间等。7.3 性能与可扩展性异步无处不在确保所有I/O操作数据库、外部API调用、文件读写都使用异步库和async/await以充分利用FastAPI的异步优势。连接池与客户端复用对于数据库和HTTP客户端如httpx.AsyncClient应该在应用生命周期内创建和复用而不是为每个请求新建。速率限制与队列如果面对高并发直接调用LLM API可能会触发速率限制。考虑引入任务队列如 Celery 或 RQ将LLM调用任务异步化并通过轮询或WebSocket通知客户端结果。缓存策略对于常见或重复的查询例如对同一问题的标准回答可以考虑在Redis等缓存中存储LLM的响应以减少API调用成本和延迟。7.4 代码组织与测试保持清晰的层次结构就像我们示例中的routers/,services/,schemas/分离这有助于单元测试和功能扩展。编写单元测试使用pytest和httpx测试你的API端点。模拟mockLLM服务层的响应确保业务逻辑正确而不会产生真实的API调用费用。# test_chat.py 示例 from fastapi.testclient import TestClient from main import app from unittest.mock import AsyncMock, patch client TestClient(app) patch(‘services.llm_service.llm_service.generate_chat_response‘, new_callableAsyncMock) async def test_chat_endpoint(mock_llm): mock_llm.return_value {“response”: “Mocked reply”, “tokens_used”: 10} response client.post(“/api/v1/chat”, json{“message”: “Hello”}) assert response.status_code 200 assert response.json()[“response”] “Mocked reply”API版本控制在路由中使用prefix”/api/v1″是一个好习惯。当API需要重大变更时可以创建v2路由并逐步迁移用户。7.5 监控与可观测性健康检查端点添加一个/health端点用于负载均衡器或监控系统检查服务状态。指标暴露使用prometheus-client等库暴露应用指标请求数、延迟、错误率、LLM调用token消耗并集成到Grafana等监控面板中。跟踪LLM成本记录每次调用的模型、token使用量并定期统计以预测和控制成本。三天的时间我们从零开始搭建了一个结构清晰、功能完整的FastAPI LLM服务。我们不仅学会了FastAPI的核心用法还实践了LLM集成、Prompt设计、会话管理以及错误处理。这个项目骨架可以作为你更复杂AI应用的起点例如增加用户认证、集成向量数据库进行知识库检索、或者接入多个不同的LLM提供商。技术的价值在于解决实际问题。接下来你可以尝试用这个服务为你自己的项目添加一个智能对话功能或者探索更复杂的Prompt模式如Chain-of-Thought甚至尝试集成LangChain等框架来构建更强大的AI工作流。如果在实践中遇到任何问题欢迎回顾本文中的代码和排查思路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价