大模型应用开发教程12 | LLMOps 与部署实战(FastAPI 后端 + 前端应用)

大模型应用开发教程12 | LLMOps 与部署实战(FastAPI 后端 + 前端应用)

理论部分

当我们把“调用模型”的代码写成脚本后,会很快遇到一个问题:脚本能跑,但离“应用”还差很远。原因是脚本天然是单机、单用户、一次性运行的形态,而应用需要:

  • 可复用:前端、其他服务、甚至不同终端都能调用
  • 可观测:能知道服务是否健康、耗时多少、报错是什么
  • 可交付:一个 URL 或一个页面,让人可以直接用

因此,最常见的工程形态是“前后端分离”:

  • 后端服务(API):统一封装模型调用,负责鉴权/限流/日志/错误处理等(本篇先做最小版本)
  • 前端应用(UI):提供交互体验,负责展示与用户输入

这一篇我们用 FastAPI 写一个最小对话服务,然后用 Streamlit 写一个最小聊天界面,把端到端链路跑通。


实践部分

本案例做什么

我们会做两件事:

  1. 启动 FastAPI 后端服务:提供/health/chat接口
  2. 启动 Streamlit 前端:把用户输入发给后端/chat,展示模型回复

主要代码 1:FastAPI 后端

脚本:src/5.2_backend_api.py

importuvicornfromfastapiimportFastAPI,HTTPExceptionfrompydanticimportBaseModelimporttimeimportosfromdotenvimportload_dotenvfromopenaiimportOpenAI# 加载环境变量load_dotenv()# 初始化 OpenAI 客户端 (智谱 AI)client=OpenAI(api_key=os.getenv("ZHIPUAI_API_KEY"),base_url=os.getenv("ZHIPUAI_BASE_URL"))app=FastAPI(title="LLM Chat API Service",description="基于 FastAPI 的大模型对话服务 (Direct API)",version="1.0.0")# === 定义请求体模型 ===classChatRequest(BaseModel):query:strmodel_name:str="glm-4-flash"# 默认模型classChatResponse(BaseModel):answer:strprocessing_time:float# === API 路由 ===@app.get("/")defread_root():return{"message":"Welcome to LLM Chat API Service! Visit /docs for Swagger UI."}@app.get("/health")defhealth_check():return{"status":"healthy","timestamp":time.time()}@app.post("/chat",response_model=ChatResponse)defchat_endpoint(request:ChatRequest):start_time=time.time()try:print(f"收到请求:{request.query}(Model:{request.model_name})")# 直接调用大模型 APIresponse=client.chat.completions.create(model=request.model_name,messages=[{"role":"system","content":"你是一个乐于助人的 AI 助手。"},{"role":"user","content":request.query}],temperature=0.7)answer=response.choices[0].message.content process_time=time.time()-start_timereturnChatResponse(answer=answer,processing_time=process_time)exceptExceptionase:print(f"Error:{e}")raiseHTTPException(status_code=500,detail=str(e))if__name__=="__main__":print("🚀 正在启动 FastAPI 后端服务 (Direct LLM)...")print("文档地址: http://127.0.0.1:8002/docs")uvicorn.run(app,host="127.0.0.1",port=8002)

主要代码 2:Streamlit 前端

脚本:src/5.2_frontend_ui.py

importstreamlitasstimportrequestsimporttime# === 配置 ===BACKEND_URL="http://127.0.0.1:8002/chat"st.set_page_config(page_title="AI 聊天助手",page_icon="🤖")# === 侧边栏 ===withst.sidebar:st.header("⚙️ 设置")model_name=st.selectbox("选择模型",["glm-4-flash","glm-4-air","glm-4-plus"])st.info("这是一个基于 FastAPI + Streamlit 的前后端分离演示应用。")st.markdown("---")st.markdown("**状态**: 🟢 后端服务需先启动")# === 主界面 ===st.title("🤖 智能对话助手 (API 版)")st.caption("🚀 由 Streamlit 和 FastAPI 驱动,直接调用大模型")# === 初始化会话状态 (History) ===if"messages"notinst.session_state:st.session_state.messages=[{"role":"assistant","content":"你好!我是你的 AI 助手,有什么可以帮你的吗?"}]# === 显示历史消息 ===formsginst.session_state.messages:withst.chat_message(msg["role"]):st.markdown(msg["content"])# === 处理用户输入 ===ifprompt:=st.chat_input("请输入你的问题..."):# 1. 显示用户消息st.session_state.messages.append({"role":"user","content":prompt})withst.chat_message("user"):st.markdown(prompt)# 2. 调用后端 API 获取回答withst.chat_message("assistant"):message_placeholder=st.empty()full_response=""try:withst.spinner("思考中..."):# 发送请求到后端payload={"query":prompt,"model_name":model_name}response=requests.post(BACKEND_URL,json=payload)ifresponse.status_code==200:data=response.json()answer=data.get("answer","")# 模拟打字机效果forchunkinanswer:full_response+=chunk message_placeholder.markdown(full_response+"▌")message_placeholder.markdown(full_response)else:st.error(f"后端报错:{response.status_code}-{response.text}")full_response="抱歉,服务暂时不可用。"exceptrequests.exceptions.ConnectionError:st.error("❌ 无法连接到后端服务。请确保 `src/5.2_backend_api.py` 正在运行。")full_response="连接失败"# 3. 保存助手回复到历史st.session_state.messages.append({"role":"assistant","content":full_response})

运行方式

第一步,启动后端(保持运行):

python3 src/5.2_backend_api.py

第二步,验证后端健康(可选):

curlhttp://127.0.0.1:8002/health

第三步,启动前端(另开一个终端):

streamlit run src/5.2_frontend_ui.py

运行结果示例

后端启动后会看到类似输出,并提示文档地址:

🚀 正在启动 FastAPI 后端服务 (Direct LLM)... 文档地址: http://127.0.0.1:8002/docs INFO: Uvicorn running on http://127.0.0.1:8002 (Press CTRL+C to quit)

访问健康检查接口会返回类似 JSON:

{"status":"healthy","timestamp":1730000000.0}

前端启动后会输出 Streamlit 的访问地址(本地一般为 8501 端口),在页面里输入问题即可得到模型回复。


总结

这一篇我们把脚本升级为可交互的应用形态:用 FastAPI 把模型调用封装为统一接口,用 Streamlit 做一个轻量前端界面,并跑通了端到端链路。

作为整个教程的收尾,我们也把 12 篇内容串起来回顾一遍。我们从最基础的环境与第一次调用开始,逐步搭起了一套完整的 LLM 应用能力栈:

  • 第 2~4 篇:跑通调用与多轮对话,理解消息列表与会话状态
  • 第 5~6 篇:掌握提示词工程与结构化输出,让结果更稳定、更可用
  • 第 7~8 篇:理解并落地 RAG,从“能检索”升级到“能基于资料回答”
  • 第 9~10 篇:跑通工具调用与 ReAct Agent,让模型具备“多步行动”能力
  • 第 11 篇:理解微调的定位与流程,知道何时需要以及产物是什么
  • 第 12 篇:完成服务化与前后端串联,把能力封装成一个可交付的应用形态

到这里,我们已经具备了从 0 到 1 开发大模型应用的完整路径:既能用 Prompt/RAG/Agent 解决效果问题,也能用 API + UI 的方式把能力交付出去。接下来如果要继续增强,就可以围绕“效果、性能、成本、安全、评测、观测”把这个应用逐步工程化。