使用Rust构建一个完整的DeepSeekWeb聊天应用

使用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生态中常用的库,主要用于构建网络服务和处理数据,各自的作用如下:

  1. axum
    基于 Tokio、Tower 构建的现代化 Web 框架,专注于简洁性和可扩展性。适合构建 REST API、HTTP 服务等,支持路由、中间件、请求/响应处理等核心 Web 功能,设计风格贴近Rust的异步编程模型。
  2. tokio
    Rust 最流行的异步运行时,提供异步 I/O、任务调度、计时器等核心能力。features = ["full"] 启用了所有功能(如多线程调度器、网络/文件系统异步操作等),是 axum 等异步框架的基础依赖。
  3. serde
    通用的数据序列化/反序列化库,支持 JSON、CSV、XML 等多种格式。features = ["derive"] 允许通过 #[derive(Serialize, Deserialize)] 自动生成序列化代码,简化数据转换逻辑。
  4. serde_json
    基于 serde 的 JSON 格式实现,提供 JSON 字符串与Rust数据结构之间的转换,常用于处理 HTTP 请求/响应中的 JSON 数据。
  5. reqwest
    异步 HTTP 客户端,支持发送 GET/POST 等请求,features = ["json"] 启用 JSON 自动序列化/反序列化功能,方便与 REST API 交互(例如服务端向其他接口发起请求)。
  6. 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::***::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 Chat***pletionRequest {
    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 API
    let response = state
        .client
        .post("https://api.deepseek.***/chat/***pletions")
        .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.***/npm/marked/marked.min.js"></script>
<script>
// 配置 marked 库
marked.setOptions({
    breaks: true,
    gfm: true,
});

// 渲染 Markdown 内容
function addMessageToHistory(role, content) {
    // ... 其他代码 ...
    if (role === 'assistant') {
        // 为AI消息渲染Markdown
        const 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.***/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.***/),了解更多资讯~

转载请说明出处内容投诉
CSS教程网 » 使用Rust构建一个完整的DeepSeekWeb聊天应用

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买