【学习记录】DeepSeek 代码助手:FastAPI 后端 + Streamlit 前端完整实现
在上一篇文章中,我们展示了如何将 DeepSeek 大模型封装为 FastAPI 服务。今天,我们为其打造一个友好的 Web 界面——DeepSeek 代码助手。用户可以通过浏览器输入编程问题,系统调用后端 DeepSeek 模型生成代码或解答,并以高亮代码块的形式展示。本文详细讲解前后端代码、运行方法、原理及注意事项,帮助你快速搭建属于自己的 AI 编程助手。
📌 目录
- 项目概览
- 后端实现:FastAPI + DeepSeek
- 2.1 依赖安装与配置
- 2.2 代码详解
- 前端实现:Streamlit 界面
- 3.1 页面布局与组件
- 3.2 调用后端 API
- 3.3 结果展示与错误处理
- 运行指南
- 4.1 启动后端服务
- 4.2 启动前端界面
- 4.3 测试效果
- 注意事项与优化建议
- 总结
一、项目概览
本系统由两部分组成:
| 组件 | 技术栈 | 职责 |
|---|---|---|
| 后端 API | FastAPI + LlamaIndex + DeepSeek | 接收用户问题及系统提示词,调用 DeepSeek 模型生成回答 |
| 前端 UI | Streamlit | 提供 Web 交互界面,发送请求并展示模型返回的代码/文本 |
工作流程:
- 用户在 Streamlit 界面输入问题(可附带系统提示词)。
- 前端向 FastAPI 后端发送 HTTP POST 请求。
- 后端调用 DeepSeek 模型,返回生成的回答。
- 前端将回答以代码块形式展示,并显示模型信息。
二、后端实现:FastAPI + DeepSeek
2.1 依赖安装
创建虚拟环境并安装以下包:
pipinstallfastapi uvicorn llama-index-core llama-index-llms-deepseek2.2 完整代码(app.py)
importosimportloggingfromfastapiimportFastAPI,HTTPExceptionfrompydanticimportBaseModel,Fieldfromllama_index.llms.deepseekimportDeepSeekfromllama_index.core.llmsimportChatMessage# 日志配置logging.basicConfig(level=logging.INFO)logger=logging.getLogger(__name__)# DeepSeek 配置(请勿硬编码!生产环境使用环境变量)DEEPSEEK_API_KEY="sk-xxxxxxxxxxxx"# 替换为你的真实 KeyDEFAULT_MODEL="deepseek-chat"llm=DeepSeek(model=DEFAULT_MODEL,api_key=DEEPSEEK_API_KEY,temperature=0.3,max_tokens=2048,timeout=60.0,)# 请求/响应模型classGenerateRequest(BaseModel):prompt:str=Field(...,description="用户输入的提示词")system_prompt:str|None=Field(None,description="可选的系统提示词")classGenerateResponse(BaseModel):response:strmodel:str# FastAPI 应用app=FastAPI(title="DeepSeek LLM API")@app.get("/health")asyncdefhealth():return{"status":"ok","model":DEFAULT_MODEL}@app.post("/generate",response_model=GenerateResponse)asyncdefgenerate_text(request:GenerateRequest):try:messages=[]ifrequest.system_prompt:messages.append(ChatMessage(role="system",content=request.system_prompt))messages.append(ChatMessage(role="user",content=request.prompt))response=llm.chat(messages)answer=response.message.contentreturnGenerateResponse(response=answer,model=DEFAULT_MODEL)exceptExceptionase:logger.error(f"推理失败:{str(e)}",exc_info=True)raiseHTTPException(status_code=500,detail=f"模型推理失败:{str(e)}")代码要点:
- 使用
DeepSeek类初始化模型,配置temperature(控制随机性)、max_tokens(输出长度)、timeout(超时)。 ChatMessage支持多轮对话,这里构造了可选的system消息和必填的user消息。/generate端点接收 JSON 格式的请求,返回模型生成的文本。- 统一异常处理,避免将内部错误直接暴露给客户端。
⚠️安全警告:API Key 硬编码在代码中,是严重的安全隐患。生产环境请使用环境变量(如
os.getenv("DEEPSEEK_API_KEY"))或密钥管理服务。
三、前端实现:Streamlit 界面
3.1 依赖安装
pipinstallstreamlit requests3.2 完整代码(ui.py)
importstreamlitasstimportrequestsimportjson# ---------- 页面配置 ----------st.set_page_config(page_title="DeepSeek 代码助手",page_icon="🤖",layout="centered")st.title("🤖 DeepSeek 代码助手")st.markdown("基于 DeepSeek 模型,专注代码生成与解答")# ---------- 侧边栏配置 ----------withst.sidebar:st.header("⚙️ 设置")backend_url=st.text_input("后端 API 地址",value="http://localhost:8000")system_prompt=st.text_area("系统提示词(可选)",value="你是一个严谨的代码助手,只输出代码和简洁注释,不要额外解释。",help="设定模型行为风格")st.markdown("---")st.markdown("### 使用说明")st.markdown("1. 在下方输入你的编程问题")st.markdown("2. 点击「生成回答」按钮")st.markdown("3. 等待模型返回代码或解答")# ---------- 主区域 ----------st.header("💬 问题输入")user_prompt=st.text_area("请输入你的问题:",height=150,placeholder="例如:用Python写一个计算斐波那契数列的函数",key="prompt_input")col1,col2=st.columns([1,5])withcol1:submit=st.button("🚀 生成回答",type="primary",use_container_width=True)# ---------- 结果展示区 ----------ifsubmit:ifnotuser_prompt.strip():st.warning("⚠️ 请输入问题内容")st.stop()api_endpoint=f"{backend_url.rstrip('/')}/generate"payload={"prompt":user_prompt,"system_prompt":system_promptifsystem_prompt.strip()elseNone}withst.spinner("🤔 DeepSeek 正在思考中,请稍候..."):try:response=requests.post(api_endpoint,json=payload,headers={"Content-Type":"application/json"},timeout=60)response.raise_for_status()result=response.json()st.success("✅ 生成成功")st.subheader("📄 回答内容")# 使用代码块展示(如果是代码会自动高亮)st.code(result["response"],language="python"if"python"inresult["response"].lower()else"text")st.caption(f"模型:{result['model']}")st.info("💡 提示:点击代码块右上角的复制图标可直接复制代码")exceptrequests.exceptions.ConnectionError:st.error(f"❌ 无法连接到后端服务,请确认后端已启动且地址正确:{backend_url}")st.info("启动后端命令:`uvicorn app:app --host 0.0.0.0 --port 8000`")exceptrequests.exceptions.Timeout:st.error("⏰ 请求超时,请稍后重试或检查模型响应时间")exceptrequests.exceptions.HTTPErrorase:st.error(f"❌ 后端返回错误:{e}\n{response.text}")exceptjson.JSONDecodeError:st.error("❌ 解析响应失败,后端可能返回了非 JSON 内容")exceptExceptionase:st.error(f"❌ 未知错误:{str(e)}")st.markdown("---")st.markdown("📌 提示:如果生成内容不全,可尝试在侧边栏修改系统提示词或检查后端 `max_tokens` 设置。")前端要点:
- 侧边栏配置:允许用户修改后端 API 地址和系统提示词,增强灵活性。
- 错误处理:覆盖连接失败、超时、HTTP 错误、JSON 解析错误等常见情况,给出友好提示。
- 结果展示:使用
st.code自动识别代码语言(简单判断是否包含“python”),支持复制功能。 - 用户体验:提交时显示加载动画(
st.spinner),成功/失败有明确的状态反馈。
四、运行指南
4.1 启动后端服务
在终端中执行:
# 设置 API Key(Linux/macOS)exportDEEPSEEK_API_KEY="sk-xxxxxxxxxxxx"# 或 Windows (cmd)setDEEPSEEK_API_KEY=sk-xxxxxxxxxxxx# 启动 FastAPI 服务uvicorn app:app--host0.0.0.0--port8000--reload看到类似输出表示成功:
INFO: Uvicorn running on http://0.0.0.0:8000 INFO: Application startup complete.4.2 启动前端界面
打开另一个终端,运行:
streamlit run ui.py浏览器将自动打开http://localhost:8501。
4.3 测试效果
- 在 Streamlit 界面的输入框中输入问题,例如:
用Python写一个快速排序函数。 - 点击「生成回答」按钮。
- 稍等片刻,后端返回的代码会显示在代码块中,并标注模型名称。
—
五、注意事项与优化建议
| 方面 | 注意事项 | 优化建议 |
|---|---|---|
| API Key 安全 | 代码中硬编码了 Key,有泄露风险 | 使用环境变量os.getenv("DEEPSEEK_API_KEY");生产环境使用密钥管理服务 |
| CORS 问题 | 前端和后端可能端口不同,但 Streamlit 默认请求后端时属于跨域?实际上 Streamlit 是客户端发送请求到后端,不涉及浏览器跨域限制。 | 无需额外配置。若前端部署在独立域名,后端需启用CORSMiddleware。 |
| 请求超时 | 模型生成较长内容可能超过 60 秒 | 可适当调高timeout参数,或改为异步任务队列 |
| 并发处理 | FastAPI 的同步llm.chat会阻塞事件循环 | 使用asyncio.to_thread将同步调用放入线程池,或改用 DeepSeek 的异步 API(如果提供) |
| 前端代码高亮 | 当前仅通过判断字符串中是否含“python”来决定高亮语言 | 可根据返回代码块中的语言标记(如```python)更精确高亮;也可使用pygments库 |
| 对话历史 | 当前仅支持单轮对话 | 扩展前端维护messages历史,并通过 API 传递完整的对话列表 |
六、总结
通过本文,我们构建了一个完整的DeepSeek 代码助手,包括:
- ✅ 基于 FastAPI 的模型调用后端,支持系统提示词和用户问题。
- ✅ 基于 Streamlit 的 Web 前端,提供直观的交互界面。
- ✅ 完善的错误处理和用户提示,提升可用性。
- ✅ 清晰的代码注释和运行指南,方便二次开发。
你可以将此系统部署在个人服务器上,作为团队内部的 AI 编程辅助工具。后续还可以扩展:
- 支持多轮对话(保存历史消息)。
- 集成代码执行环境(如 Jupyter 内核)。
- 添加用户认证与计费功能。
希望这篇文章能帮助你快速搭建自己的大模型应用。如果在实践过程中遇到问题,欢迎在评论区留言交流。