使用Rust构建一个完整的DeepSeekWeb聊天应用
在现代软件开发中,Rust 正在成为构建高性能、可靠应用程序的首选语言之一。今天,我将分享如何使用Rust构建一个完整的 Web 聊天应用,它能够与 DeepSeek API 交互,提供类似 ChatGPT 的体验。
项目概览
我们的目标是创建一个功能完整的聊天应用,它包含:
- 一个基于 Axum 的后端服务
- 一个带有 Markdown 渲染功能的前端界面
- 与 DeepSeek API 的集成
- 良好的错误处理和用户体验
技术栈选择
对于这个项目,我们选择了以下技术栈:
- Axum:一个模块化、快速、简洁的RustWeb 框架
- Tokio:异步运行时,用于处理并发请求
- Reqwest:用于发送 HTTP 请求到 DeepSeek API
- Serde:用于 JSON 序列化和反序列化
- Tower HTTP:提供静态文件服务等功能
- Marked.js:前端 Markdown 渲染库
项目结构
deepseek_web/
├── Cargo.toml
├── src/
│ └── main.rs
└── static/└── index.html

实现细节
Cargo.toml配置
[package]
name = "deepseek_web"
version = "0.1.0"
edition = "2021"[dependencies]
axum = "0.6"
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.11", features = ["json"] }
tower-http = { version = "0.4", features = ["cors", "fs"] }
这几个dependencies是Rust生态中常用的库,主要用于构建网络服务和处理数据,各自的作用如下:
- axum
基于 Tokio、Tower 构建的现代化 Web 框架,专注于简洁性和可扩展性。适合构建 REST API、HTTP 服务等,支持路由、中间件、请求/响应处理等核心 Web 功能,设计风格贴近Rust的异步编程模型。 - tokio
Rust 最流行的异步运行时,提供异步 I/O、任务调度、计时器等核心能力。features = ["full"]启用了所有功能(如多线程调度器、网络/文件系统异步操作等),是 axum 等异步框架的基础依赖。 - serde
通用的数据序列化/反序列化库,支持 JSON、CSV、XML 等多种格式。features = ["derive"]允许通过#[derive(Serialize, Deserialize)]自动生成序列化代码,简化数据转换逻辑。 - serde_json
基于 serde 的 JSON 格式实现,提供 JSON 字符串与Rust数据结构之间的转换,常用于处理 HTTP 请求/响应中的 JSON 数据。 - reqwest
异步 HTTP 客户端,支持发送 GET/POST 等请求,features = ["json"]启用 JSON 自动序列化/反序列化功能,方便与 REST API 交互(例如服务端向其他接口发起请求)。 - tower-http
基于 Tower 生态的 HTTP 中间件集合。cors功能提供跨域资源共享(CORS)支持,fs支持静态文件服务,常用于 axum 等框架中扩展 HTTP 处理能力。
这些库组合起来,通常用于构建一个完整的异步 Web 服务:axum 处理 HTTP 路由和逻辑,tokio 提供异步运行时,serde 系列处理数据序列化,reqwest 用于服务端发起 HTTP 请求,tower-http 补充中间件功能(如跨域、静态文件)。
1. 后端实现
后端使用 Axum 框架构建,主要包含以下组件:
// 主要依赖
use axum::{extract::State,http::StatusCode,response::Html,routing::{get, post},Json, Router,
};
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};
use tower_http::services::ServeDir;
use std::net::SocketAddr;
use std::env;
我们定义了与 DeepSeek API 交互所需的数据结构:
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "lowercase")]
enum Role {System,User,Assistant,
}#[derive(Serialize, Deserialize, Debug, Clone)]
struct Message {role: Role,content: String,
}#[derive(Serialize, Deserialize, Debug)]
struct ChatCompletionRequest {model: String,messages: Vec<Message>,stream: bool,
}
核心的聊天处理函数负责与 DeepSeek API 通信:
async fn chat_handler(State(state): State<AppState>,Json(request): Json<ChatRequest>,
) -> Result<Json<ChatResponse>, (StatusCode, Json<ErrorResponse>)> {// 获取API密钥let api_key = env::var("DEEPSEEK_API_KEY").map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, Json(ErrorResponse { error: "服务器未正确配置: 未设置 DEEPSEEK_API_KEY 玱境变量".to_string()})))?;// 添加用户消息到历史let user_message = Message {role: Role::User,content: request.message.clone(),};// ... 处理逻辑 ...// 发送请求到 DeepSeek APIlet response = state.client.post("https://api.deepseek.com/chat/completions").header("Content-Type", "application/json").header("Authorization", format!("Bearer {}", api_key)).json(&request_body).send().await.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(ErrorResponse { error: format!("网络请求失败: {}", e)})))?;// ... 处理响应 ...
}
2. 错误处理
一个健壮的应用需要良好的错误处理机制。我们在程序启动时检查必要的环境变量:
#[tokio::main]
async fn main() {// 检查是否设置了 API 密钥if env::var("DEEPSEEK_API_KEY").is_err() {eprintln!("错误: 未设置 DEEPSEEK_API_KEY 环境变量");eprintln!("请设置环境变量,例如: export DEEPSEEK_API_KEY=your_api_key_here");std::process::exit(1);}// ... 其余初始化代码 ...
}
这种方法确保了在缺少必要配置时,应用能够提供清晰的错误信息而不是神秘的崩溃。
3. 前端实现
前端使用原生 HTML、CSS 和 JavaScript 构建,集成了 Marked.js 库来渲染 Markdown:
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
// 配置 marked 库
marked.setOptions({breaks: true,gfm: true,
});// 渲染 Markdown 内容
function addMessageToHistory(role, content) {// ... 其他代码 ...if (role === 'assistant') {// 为AI消息渲染Markdownconst contentDiv = document.createElement('div');contentDiv.className = 'assistant-message-content';contentDiv.innerHTML = marked.parse(content);messageDiv.appendChild(contentDiv);}// ... 其他代码 ...
}
</script>
4. 用户体验优化
为了提供更好的用户体验,我们实现了以下功能:
- 实时加载指示器
- 响应式设计,适配移动设备
- 快捷键支持(Ctrl+Enter 发送消息)
- 自动滚动到最新消息
- Markdown 渲染支持
部署和运行

要运行这个应用,首先需要设置 DeepSeek API 密钥。如上图所述,秘钥可以到https://platform.deepseek.com/api_keys申请:
export DEEPSEEK_API_KEY=your_actual_api_key_here
然后启动应用:
cargo run

应用将在 http://127.0.0.1:3000 上运行。
效果展示

可以看到,我们实现了一个类似大模型聊天的应用。DeepSeek返回的markdown格式内容也能够被正确渲染展示,效果还是不错的。
总结
通过这个项目,我们展示了如何使用Rust构建一个完整的 Web 应用。Axum 框架提供了简洁而强大的 API 来处理 HTTP 请求,Tokio 提供了高效的异步运行时,而 Reqwest 使得与外部 API 的交互变得简单。
这个应用不仅功能完整,还具有良好的错误处理机制和用户体验。它展示了Rust在构建现代 Web 应用方面的潜力,既保证了性能,又确保了安全性。如果你对Rust感兴趣,或者想构建自己的 AI 聊天应用,这个项目是一个很好的起点。你可以根据自己的需求进行扩展,比如添加用户认证、持久化聊天历史、支持更多 AI 模型等功能。
想了解更多关于Rust语言的知识及应用,可前往华为开放原子旋武开源社区(https://xuanwu.openatom.cn/),了解更多资讯~
