FastAPI 项目实战:LLM 流式对话接口优化与简历投递功能实现
1. 项目背景与需求分析在当前的 AI 应用开发中大语言模型LLM的集成已成为标配功能。本文基于一个真实的 FastAPI 项目分享两个核心功能的实现与优化LLM 流式对话接口优化从单轮对话升级为多轮对话并改进错误处理机制简历投递详情接口为求职者提供详细的投递记录查询功能2. 代码变更概览2.1 文件结构变更37 -28 app/apis/llm/case1_api.py # LLM 流式对话接口优化 1 -1 app/apis/llm/case2_api.py # API 端点基础 URL 更新 16 -3 app/schemas/llm_case1.py # 新增多轮对话数据结构2.2 核心优化点LLM 接口升级单轮对话 → 多轮对话错误处理优化避免 SSE 流异常导致前端无响应API 端点统一标准化阿里云 DashScope API 调用新增简历投递详情接口完善求职功能3. LLM 流式对话接口优化3.1 原单轮对话接口llm_day01_router.post(/case1,summaryLLM-DAY01-CASE1)asyncdefcase1_api(llmCase1Request:LLMCase1):clientOpenAI(api_keyos.getenv(DASHSCOPE_API_KEY),base_urlhttps://ws-d765zw587c5lpqzq.cn-beijing.maas.aliyuncs.com/compatible-mode/v1,)promptf #角色设定{llmCase1Request.role}#用户问题{llmCase1Request.question}completionclient.chat.completions.create(modelqwen-plus,messages[{role:system,content:你是一个智能助手},{role:user,content:prompt},],streamTrue,stream_options{include_usage:True})return{code:1,message:success,data:completion}3.2 优化后的多轮对话接口llm_day01_router.post(/case2,summary多轮对话流式输出)asyncdefcase2_api(req:LLMMultiChat):msgs[{role:m.role,content:m.content}forminreq.messages]returnStreamingResponse(contentstream_chunk(msgs),media_typetext/event-stream)3.3 改进的流式生成器defstream_chunk(messages:list):多轮流式生成器接收完整对话历史system 历史轮次 当前问题逐块 yield SSE data 异常处理OpenAI SDK 抛出的异常如 AuthenticationError、RateLimitError 不会再导致 StreamingResponse 返回 500 前端 SSE 响应体为空。 改为把错误信息作为特殊 SSE 块 yield 给前端前端会展示明确错误。 clientOpenAI(api_keyos.getenv(DASHSCOPE_API_KEY),base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1,)try:completionclient.chat.completions.create(modelqwen-plus,messagesmessages,streamTrue,stream_options{include_usage:True})forchunkincompletion:ifchunk.choices:choicechunk.choices[0]ifchoice.delta:deltachoice.deltaifdelta.content:yieldfdata:{delta.content}\n\nyielddata: [done]\n\nexceptExceptionase:# 把异常信息透传给前端避免 SSE 流截断导致前端看不到具体原因err_typetype(e).__name__ err_msgstr(e).replace(\n, ).strip()[:500]yieldfdata: [ERROR]{err_type}:{err_msg}\n\nyielddata: [done]\n\n3.4 关键优化点解析3.4.1 多轮对话支持原接口仅支持单轮问答每次请求都是独立的对话新接口支持完整的对话历史可以维护上下文连贯性实现方式通过LLMMultiChat数据结构传递完整的消息列表3.4.2 异常处理优化问题原实现中OpenAI SDK 异常会导致 StreamingResponse 返回 500 状态码前端 SSE 连接中断解决方案使用 try-except 包裹流式生成逻辑将异常信息通过 SSE 通道透传给前端优势前端可以正常接收错误信息并展示给用户而不是连接突然中断3.4.3 API 端点标准化# 优化前base_urlhttps://ws-d765zw587c5lpqzq.cn-beijing.maas.aliyuncs.com/compatible-mode/v1# 优化后base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1统一使用阿里云 DashScope 的标准兼容模式端点提高代码的可维护性和可移植性4. 数据结构定义优化4.1 新增多轮对话数据结构fromtypingimportListfrompydanticimportBaseModel,FieldclassLLMCase1(BaseModel):question:strField(...,title问题,description问题)classLLMCase2(BaseModel):user_id:intField(...,title用户ID,description用户ID)session_id:strField(...,title会话ID,description会话ID)message:strField(...,title用户消息,description用户消息)# 新增多轮对话数据结构classLLMMultiChat(BaseModel):messages:List[dict]Field(...,title对话消息列表,description包含角色和内容的完整对话历史)4.2 数据结构设计思路LLMCase1保持向后兼容用于简单的单轮问答场景LLMCase2支持用户会话管理适合需要维护对话状态的场景LLMMultiChat全新的多轮对话支持可以传递完整的对话上下文5. 简历投递详情接口实现5.1 新增接口代码job_router.get(/resume_submission_detail/{id},summary简历投递详情)asyncdefresume_submission_detail(id:int):resawaitJobService.resume_submission_detail(id)return{code:1,message:ok,data:json.loads(res)}5.2 接口设计要点RESTful 设计使用GET /resume_submission_detail/{id}路径参数验证通过路径参数id接收投递记录 ID服务层调用委托给JobService.resume_submission_detail处理业务逻辑数据格式化使用json.loads()确保返回标准化的 JSON 数据5.3 与原接口的对比# 原接口查看我的投递记录列表job_router.get(/get_my_submissions,summary查看我的投递记录)asyncdefget_my_submissions():求职者查看自己的投递记录需候选人Token鉴权resawaitJobService.getMySubmissions(job_seeker_id,page,page_size)return{code:1,message:查询成功,data:res}# 新接口查看单条投递记录详情job_router.get(/resume_submission_detail/{id},summary简历投递详情)asyncdefresume_submission_detail(id:int):resawaitJobService.resume_submission_detail(id)return{code:1,message:ok,data:json.loads(res)}6. 技术实现细节6.1 SSEServer-Sent Events流式传输# 核心实现defstream_chunk(messages:list):# ... 流式生成逻辑 ...forchunkincompletion:ifchunk.choices:choicechunk.choices[0]ifchoice.delta:deltachoice.deltaifdelta.content:yieldfdata:{delta.content}\n\n# SSE 格式yielddata: [done]\n\n# 结束标记SSE 格式要求每行以data:开头每段数据以两个换行符\n\n结束特殊标记[done]表示流结束错误信息格式data: [ERROR] {错误类型}: {错误信息}6.2 异常处理机制try:# 正常的流式生成逻辑completionclient.chat.completions.create(...)# ... 处理正常流 ...exceptExceptionase:# 异常处理将错误信息通过 SSE 通道返回err_typetype(e).__name__ err_msgstr(e).replace(\n, ).strip()[:500]# 限制长度避免过大yieldfdata: [ERROR]{err_type}:{err_msg}\n\nyielddata: [done]\n\n异常类型处理AuthenticationErrorAPI 密钥错误RateLimitError请求频率超限APIConnectionError网络连接问题其他未知异常6.3 依赖注入设计fromfastapiimportDepends,APIRouter,Queryfromapp.core.dependsimportget_job_info,get_job_seeker_info,get_enterprise_info# 依赖注入示例asyncdefget_my_submissions(job_seeker_id:intDepends(get_job_seeker_info),page:intQuery(1,ge1),page_size:intQuery(10,ge1,le100)):# 业务逻辑pass7. 前端集成建议7.1 SSE 客户端实现// 前端 SSE 客户端示例asyncfunctionstreamLLMResponse(messages){consteventSourcenewEventSource(/api/llm-day01/case2);eventSource.onmessage(event){constdataevent.data;if(data[done]){eventSource.close();console.log(流式传输完成);}elseif(data.startsWith([ERROR])){eventSource.close();consterrorMsgdata.substring(8);// 移除 [ERROR] console.error(流式传输错误:,errorMsg);// 显示错误信息给用户}else{// 正常的数据块追加到界面appendToChat(data);}};eventSource.onerror(error){console.error(SSE 连接错误:,error);eventSource.close();};}7.2 错误处理优化// 改进的错误处理functionhandleSSEError(errorData){consterrorPrefix[ERROR] ;if(errorData.startsWith(errorPrefix)){consterrorInfoerrorData.substring(errorPrefix.length);const[errorType,...errorMsgParts]errorInfo.split(: );consterrorMessageerrorMsgParts.join(: );// 根据错误类型提供不同的用户提示switch(errorType){caseAuthenticationError:showToast(API 密钥错误请检查配置);break;caseRateLimitError:showToast(请求频率超限请稍后重试);break;default:showToast(系统错误:${errorMessage});}returntrue;// 已处理错误}returnfalse;// 不是错误信息}8. 部署与配置8.1 环境变量配置# .env 文件配置DASHSCOPE_API_KEYyour_dashscope_api_key_hereBASE_URLhttps://dashscope.aliyuncs.com/compatible-mode/v1MODEL_NAMEqwen-plus8.2 Docker 部署配置# Dockerfile 示例 FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD [uvicorn, app.main:app, --host, 0.0.0.0, --port, 8000]8.3 Nginx 配置SSE 支持# nginx.conf 片段 server { listen 80; server_name your-domain.com; location /api/ { proxy_pass http://backend:8000; proxy_http_version 1.1; proxy_set_header Connection ; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # SSE 相关配置 proxy_buffering off; proxy_cache off; proxy_read_timeout 86400s; proxy_send_timeout 86400s; } }9. 性能优化建议9.1 连接池管理# 使用连接池管理 OpenAI 客户端importhttpxfromopenaiimportOpenAIclassLLMClientPool:def__init__(self):self._clients{}defget_client(self,api_key:str)-OpenAI:ifapi_keynotinself._clients:http_clienthttpx.AsyncClient(limitshttpx.Limits(max_connections100,max_keepalive_connections20),timeouthttpx.Timeout(30.0))self._clients[api_key]OpenAI(api_keyapi_key,base_urlhttps://dashscope.aliyuncs.com/compatible-mode/v1,http_clienthttp_client)returnself._clients[api_key]9.2 流式响应优化# 添加响应头优化llm_day01_router.post(/case2,summary多轮对话流式输出)asyncdefcase2_api(req:LLMMultiChat):msgs[{role:m.role,content:m.content}forminreq.messages]returnStreamingResponse(contentstream_chunk(msgs),media_typetext/event-stream,headers{Cache-Control:no-cache,X-Accel-Buffering:no,# 禁用 Nginx 缓冲Connection:keep-alive})10. 总结与展望10.1 本次优化的核心价值用户体验提升多轮对话支持让 AI 交互更加自然连贯错误处理完善SSE 流的异常处理机制提高了系统稳定性代码可维护性统一 API 端点和标准化的数据结构设计功能完整性简历投递详情接口完善了求职功能模块10.2 未来优化方向对话状态管理引入 Redis 缓存对话历史支持长期会话流控与限流基于用户或 IP 的请求频率限制监控与日志详细的性能监控和错误日志记录多模型支持扩展支持其他 LLM 提供商OpenAI、Claude 等10.3 最佳实践建议始终使用 try-except包裹外部 API 调用为 SSE 流设置合理的超时时间在前端实现优雅的重连机制定期更新 API 客户端库以获取最新的功能和安全修复通过本次代码优化我们不仅提升了系统的稳定性和用户体验还为未来的功能扩展奠定了良好的架构基础。这种渐进式的优化方式值得在大型项目中推广。

相关新闻

一篇文章搞懂 10 个核心概念AI AGENT和AI

一篇文章搞懂 10 个核心概念AI AGENT和AI

Agent & AI 名词大扫盲:一篇文章搞懂 10 个核心概念 你是不是经常在 AI 圈听到一堆名词——大模型、Agent、RAG、MCP、Function Call……每个都似懂非懂?这篇文章用最通俗的语言,一口气帮你扫清 10 个高频 AI 术语。 1. 什么是大模型&…

2026/10/15 21:10:35 阅读更多 →
推荐题目:洛谷 P12792 [NERC 2022] Cactus Meets Torus

推荐题目:洛谷 P12792 [NERC 2022] Cactus Meets Torus

推荐题目:洛谷 P12792 [NERC 2022] Cactus Meets Torus 题目描述 Alice 有一个漂亮的仙人掌图,她想把它画在一张纸上。Eve 威胁说要拿走这个仙人掌图的一个环,并沿着这个环上的所有边把纸剪开。这样一来,这张纸就会被分成两部分…

2026/10/17 16:59:21 阅读更多 →
Python爬取央视视频实战:从抓包到完整下载的完整流程

Python爬取央视视频实战:从抓包到完整下载的完整流程

一、环境准备 import requests import json import re import subprocess # 调用FFmpeg合并分片 需要安装:requests(HTTP请求)、FFmpeg(处理视频流)。 二、抓包定位接口 用F12或Charles抓包,聚焦央视App播…

2026/10/17 12:21:18 阅读更多 →

最新新闻

esp-adf环境搭建-基于vscode插件扩展:把settings.json改到TaoToken统一Key通道

esp-adf环境搭建-基于vscode插件扩展:把settings.json改到TaoToken统一Key通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 16:59:03 阅读更多 →
CLI-Anything:命令行原生智能体范式

CLI-Anything:命令行原生智能体范式

1. 项目概述:CLI-Anything 不是又一个命令行工具,而是一套“命令行原生”的智能体交互范式你有没有过这种体验:在终端里敲下git status,心里却想着“要是它能自动告诉我哪些文件该加进暂存区、哪些可能漏了.gitignore规则就好了”…

2026/10/17 16:59:03 阅读更多 →
AI论文工具实测:从选题到答辩的效率与避坑指南

AI论文工具实测:从选题到答辩的效率与避坑指南

每年到了毕业季,总有人在群里问同一个问题:“有没有好用的AI论文工具?求推荐。”问的人多,踩坑的人更多——有人花了几个月时间试了十来个平台,最后发现生成内容既不能用、引用还是编的;也有人被号称“一键…

2026/10/17 16:59:03 阅读更多 →
Superpowers智能编程工具链:本地化AI开发工作流实战指南

Superpowers智能编程工具链:本地化AI开发工作流实战指南

1. 这不是魔法,是开发者正在用的“超能力”工具链最近在几个技术社区和内部开发群聊里,“superpowers”这个词出现频率高得有点反常——它既不是某个新发布的开源框架,也不是某家大厂的神秘项目代号,而是一整套正在被真实工程团队…

2026/10/17 16:59:03 阅读更多 →
AI电销机器人源码部署全指南:从架构拆解到上线调优

AI电销机器人源码部署全指南:从架构拆解到上线调优

简介:这是一份面向智能电销机器人部署的源码项目包,适合具备基础Linux操作经验、希望快速上手安装自动外呼系统的开发者或运维人员,对想了解服务器部署全流程的新手也颇为友好。压缩包共3个文件,以HTML页面承载部署教程&#xff0…

2026/10/17 16:59:03 阅读更多 →
AI辅助专著写作全流程:从选题到定稿的实操指南

AI辅助专著写作全流程:从选题到定稿的实操指南

写一本专著,对绝大多数人来说,第一反应都是“这事太大了”。从选题、搭框架、找文献、写初稿,到来回改格式、统一术语、核对引用,随便哪一环拎出来都够磨掉几个月。更要命的是,很多内容领域里的资深从业者,…

2026/10/17 16:58:03 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →