WebApi 通讯-DeepSeek API调用文档

本文档基于自写的 WebApi 调用DeepSeek API项目编写,讲解 WebApi 通讯的原理、及每个方法的实现细节。

本文只用于对该项目的技术分析。项目为自用项目,源码不对外开源。

目录

  1. 项目概述
  2. 项目结构
  3. 核心类详解
  4. HTTP通信原理
  5. 代码使用示例
  6. 数据模型
  7. 常见问题

1. 项目概述

1.1 项目简介

本项目是一个基于 WinForms 的上位机应用程序,演示如何通过 WebApi 调用 DeepSeek V3 大语言模型。

1.2 技术栈

技术 版本 说明
.NET Framework 4.8 运行时环境
C# - 开发语言
WinForms - UI框架
HttpClient - .NET内置HTTP客户端
Newtonsoft.Json 13.0.4 JSON序列化库

1.3 项目特点

  • 分层架构:HTTP层、业务层、UI层分离
  • 异步支持:提供同步和异步两种调用方式
  • 多轮对话:支持上下文记忆的对话功能
  • Token统计:实时显示输入/输出/总计Token数

2. 项目结构

2.1 文件结构

复制代码
WebApi_DeepSeek/
├── WebApiHelper.cs      # HTTP通信工具类(参考速控云)
├── DeepSeekApi.cs       # DeepSeek业务API类(参考DeviceApi)
├── Form1.cs             # 主窗体逻辑代码(参考FrmMain)
├── Form1.Designer.cs    # 主窗体设计器代码
├── Program.cs           # 程序入口
├── App.config           # 应用配置文件
└── packages.config      # NuGet包依赖

2.2 架构对比

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                        速控云项目结构                            │
├─────────────────────────────────────────────────────────────────┤
│  WebApiHelper.cs  →  HTTP通信封装                                │
│  DeviceApi.cs    →  业务API封装(登录、项目、变量读写)          │
│  FrmMain.cs      →  主窗体逻辑                                   │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                        DeepSeek项目结构                          │
├─────────────────────────────────────────────────────────────────┤
│  WebApiHelper.cs  →  HTTP通信封装(相同模式)                    │
│  DeepSeekApi.cs  →  业务API封装(聊天、模型列表)                │
│  Form1.cs        →  主窗体逻辑(相同模式)                       │
└─────────────────────────────────────────────────────────────────┘

2.3 调用流程图

复制代码
┌─────────────┐
│   用户界面   │  Form1.cs
│   Form1     │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│ DeepSeekApi │  业务层
│  封装业务   │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│WebApiHelper │  HTTP层
│  封装请求   │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│ DeepSeek    │  服务端
│    API      │
└─────────────┘

3. 核心类详解

3.1 WebApiHelper - HTTP通信工具类

文件位置 : WebApiHelper.cs

作用: 封装所有HTTP请求操作,提供统一的HTTP通信接口。

类结构
csharp 复制代码
public class WebApiHelper
{
    // 静态HttpClient实例
    private static HttpClient _httpClient = new HttpClient();

    // 自定义响应类
    public class RestResponse { ... }

    // 方法列表
    public static RestResponse HttpPost<T>(string url, T body)
    public static Task<RestResponse> HttpPostAsync<T>(string url, T body)
    public static RestResponse HttpPostBearerToken<T>(string url, string token, T body)
    public static Task<RestResponse> HttpPostBearerTokenAsync<T>(string url, string token, T body)
    public static RestResponse HttpPost(string url, Dictionary<string, string> para)
    public static RestResponse HttpGet(string url)
    public static Task<RestResponse> HttpGetAsync(string url)
    public static RestResponse HttpGetBearerToken(string url, string token)
}
方法详解
HttpPostBearerToken - 带Token的POST请求
csharp 复制代码
/// <summary>
/// POST请求 - 携带Bearer Token认证
/// </summary>
/// <typeparam name="T">请求体类型</typeparam>
/// <param name="url">API地址</param>
/// <param name="token">认证令牌</param>
/// <param name="body">请求体对象</param>
/// <returns>响应对象</returns>
public static RestResponse HttpPostBearerToken<T>(string url, string token, T body)
{
    try
    {
        // 1. 将对象序列化为JSON
        string json = JsonConvert.SerializeObject(body);

        // 2. 创建StringContent,设置UTF-8编码和JSON格式
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        // 3. 创建HTTP请求
        using (var request = new HttpRequestMessage(HttpMethod.Post, url))
        {
            request.Content = content;

            // 4. 添加Bearer Token认证头
            request.Headers.Add("Authorization", $"Bearer {token}");

            // 5. 发送请求
            var response = _httpClient.SendAsync(request).Result;
            var responseBody = response.Content.ReadAsStringAsync().Result;

            // 6. 返回自定义响应对象
            return new RestResponse
            {
                Content = responseBody,
                StatusCode = (int)response.StatusCode,
                ErrorMessage = !response.IsSuccessStatusCode ? response.ReasonPhrase : null
            };
        }
    }
    catch (Exception ex)
    {
        return new RestResponse
        {
            Content = null,
            StatusCode = 500,
            ErrorMessage = ex.Message
        };
    }
}
RestResponse 响应类
csharp 复制代码
/// <summary>
/// 自定义HTTP响应类(兼容RestSharp的IRestResponse)
/// </summary>
public class RestResponse
{
    /// <summary>响应内容(JSON字符串)</summary>
    public string Content { get; set; }

    /// <summary>HTTP状态码(200/401/500等)</summary>
    public int StatusCode { get; set; }

    /// <summary>是否成功(2xx状态码)</summary>
    public bool IsSuccessful => StatusCode >= 200 && StatusCode < 300;

    /// <summary>错误消息</summary>
    public string ErrorMessage { get; set; }
}

3.2 OperateResult - 操作结果封装类

作用: 统一封装API调用的结果,提供成功/失败状态和消息。

csharp 复制代码
/// <summary>
/// 操作结果封装类
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
public class OperateResult<T>
{
    /// <summary>是否成功</summary>
    public bool IsSuccess { get; set; }

    /// <summary>消息</summary>
    public string Message { get; set; }

    /// <summary>数据内容</summary>
    public T Content { get; set; }

    /// <summary>HTTP状态码</summary>
    public int StatusCode { get; set; }

    /// <summary>
    /// 创建成功结果
    /// </summary>
    public static OperateResult<T> CreateSuccessResult(T content)
    {
        return new OperateResult<T>
        {
            IsSuccess = true,
            Message = "操作成功",
            Content = content,
            StatusCode = 200
        };
    }

    /// <summary>
    /// 创建失败结果
    /// </summary>
    public static OperateResult<T> CreateFailResult(string message, int statusCode = 400)
    {
        return new OperateResult<T>
        {
            IsSuccess = false,
            Message = message,
            Content = default(T),
            StatusCode = statusCode
        };
    }

    /// <summary>
    /// 从HTTP响应创建结果
    /// </summary>
    public static OperateResult<T> FromResponse(WebApiHelper.RestResponse response)
    {
        if (response.IsSuccessful)
        {
            try
            {
                T content = JsonConvert.DeserializeObject<T>(response.Content);
                return CreateSuccessResult(content);
            }
            catch (Exception ex)
            {
                return CreateFailResult($"JSON解析错误: {ex.Message}");
            }
        }
        else
        {
            return CreateFailResult($"HTTP错误: {response.StatusCode} - {response.ErrorMessage}", response.StatusCode);
        }
    }
}

3.3 DeepSeekApi - 业务API类

文件位置 : DeepSeekApi.cs

作用: 封装DeepSeek API的所有业务操作。

类结构
csharp 复制代码
public class DeepSeekApi
{
    // API端点
    private string ChatUrl = string.Empty;      // 聊天API
    private string ModelsUrl = string.Empty;    // 模型列表API
    private string token = string.Empty;        // 认证令牌

    // 构造函数
    public DeepSeekApi(string baseUrl)

    // 设置Token
    public void SetToken(string token)

    // 同步方法
    public OperateResult<ChatResponse> SendChat(...)
    public OperateResult<ChatResponse> SendChat(List<Message> messages, ...)
    public OperateResult<ModelsResponse> GetModels()

    // 异步方法
    public Task<OperateResult<ChatResponse>> SendChatAsync(...)
    public Task<OperateResult<ChatResponse>> SendChatAsync(List<Message> messages, ...)
}
初始化示例
csharp 复制代码
// 创建API客户端
DeepSeekApi api = new DeepSeekApi("https://xxx.cn-xxx.xxx.com");

// 设置认证Token
api.SetToken("your-api-token-here");

// 调用API
var result = api.SendChat("你好,请介绍一下自己");

if (result.IsSuccess)
{
    string reply = result.Content.choices[0].message.content;
    Console.WriteLine(reply);
}

3.4 Form1 - 主窗体

文件位置 : Form1.cs

作用: 用户界面,处理用户交互和显示结果。

关键方法
csharp 复制代码
/// <summary>
/// 发送按钮点击事件
/// </summary>
private async void btn_Send_Click(object sender, EventArgs e)
{
    string question = this.txt_Question.Text.Trim();

    // 验证输入
    if (string.IsNullOrEmpty(question))
    {
        MessageBox.Show("请输入问题", "提示");
        return;
    }

    // 禁用发送按钮
    this.btn_Send.Enabled = false;
    this.txt_Question.Enabled = false;

    try
    {
        // 显示用户问题
        AppendMessage("用户", question, Color.Blue);

        // 添加用户消息到历史
        conversationHistory.Add(new DeepSeekApi.Message
        {
            role = "user",
            content = question
        });

        // 第一次对话添加系统消息
        if (conversationHistory.Count == 1)
        {
            conversationHistory.Insert(0, new DeepSeekApi.Message
            {
                role = "system",
                content = "你是一个人工智能助手,请用简洁明了的语言回答问题。"
            });
        }

        // 调用API - 异步方法
        var result = await deepSeekApi.SendChatAsync(conversationHistory);

        // 处理响应
        if (result.IsSuccess)
        {
            var aiMessage = result.Content.choices[0].message;
            conversationHistory.Add(aiMessage);

            AppendMessage("DeepSeek", aiMessage.content, Color.Green);

            // 更新Token统计
            this.lbl_token.Text = $"{result.Content.usage.total_tokens} tokens";
            this.lbl_prompt.Text = $"输入: {result.Content.usage.prompt_tokens}";
            this.lbl_completion.Text = $"输出: {result.Content.usage.completion_tokens}";
        }
        else
        {
            AppendMessage("错误", result.Message, Color.Red);
        }
    }
    catch (Exception ex)
    {
        AppendMessage("异常", $"发生错误: {ex.Message}", Color.Red);
    }
    finally
    {
        // 恢复控件状态
        this.btn_Send.Enabled = true;
        this.txt_Question.Enabled = true;
        this.txt_Question.Clear();
        this.txt_Question.Focus();
    }
}

4. HTTP通信原理

4.1 完整通信流程

复制代码
┌─────────────┐                                      ┌─────────────┐
│   客户端     │                                      │   服务器     │
│  Client     │                                      │   Server    │
└──────┬──────┘                                      └──────┬──────┘
       │                                                    │
       │ ① 构建HTTP请求                                       │
       │    - 请求行: POST /api/v3/chat/completions          │
       │    - 请求头: Authorization: Bearer xxx              │
       │    - 请求体: {"model":"...","messages":[...]}        │
       │                                                    │
       ├────────────────────── ② 发送请求 ──────────────────▶│
       │                                                    │
       │                                    ③ 处理请求        │
       │                                    - 验证Token       │
       │                                    - 调用AI模型      │
       │                                    - 生成回复        │
       │                                                    │
       │◀──────────────────── ④ 返回响应 ───────────────────┤
       │    HTTP/1.1 200 OK                                  │
       │    {"choices":[{"message":{...}}],"usage":{...}}    │
       │                                                    │
       │ ⑤ 解析响应                                          │
       │    - 检查状态码                                      │
       │    - JSON反序列化                                    │
       │    - 提取回复内容                                    │
       │                                                    │
       ▼                                                    ▼

5. 代码使用示例

5.1 简单对话示例

csharp 复制代码
using WebApi_DeepSeek;

// 1. 创建API客户端
var api = new DeepSeekApi("https://xxx.cn-xxx.xxx.com");
api.SetToken("your-api-token");

// 2. 发送问题(同步方式)
var result = api.SendChat("什么是xxxxx?");

// 3. 检查结果
if (result.IsSuccess)
{
    string reply = result.Content.choices[0].message.content;
    int tokens = result.Content.usage.total_tokens;

    Console.WriteLine($"AI回复: {reply}");
    Console.WriteLine($"消耗Token: {tokens}");
}
else
{
    Console.WriteLine($"请求失败: {result.Message}");
}

5.2 多轮对话示例

csharp 复制代码
// 1. 创建对话历史
var messages = new List<DeepSeekApi.Message>
{
    new DeepSeekApi.Message { role = "system", content = "你是一个专业的编程助手" }
};

// 2. 第一轮对话
messages.Add(new DeepSeekApi.Message { role = "user", content = "什么是xxx?" });
var result1 = await api.SendChatAsync(messages);
if (result1.IsSuccess)
{
    var reply = result1.Content.choices[0].message;
    messages.Add(reply);  // 添加AI回复到历史
    Console.WriteLine($"AI: {reply.content}");
}

// 3. 第二轮对话(带上下文)
messages.Add(new DeepSeekApi.Message { role = "user", content = "它和xxx有什么区别?" });
var result2 = await api.SendChatAsync(messages);
if (result2.IsSuccess)
{
    var reply = result2.Content.choices[0].message;
    Console.WriteLine($"AI: {reply.content}");
}

5.3 异步调用示例(WinForms)

csharp 复制代码
private async void btnSend_Click(object sender, EventArgs e)
{
    btnSend.Enabled = false;

    try
    {
        // 异步调用,不阻塞UI
        var result = await deepSeekApi.SendChatAsync(txtQuestion.Text);

        if (result.IsSuccess)
        {
            txtResult.Text = result.Content.choices[0].message.content;
        }
        else
        {
            MessageBox.Show($"错误: {result.Message}");
        }
    }
    finally
    {
        btnSend.Enabled = true;
    }
}

5.4 获取模型列表

csharp 复制代码
// 获取可用模型
var result = api.GetModels();

if (result.IsSuccess)
{
    foreach (var model in result.Content.data)
    {
        Console.WriteLine($"模型ID: {model.id}");
        Console.WriteLine($"所有者: {model.owned_by}");
    }
}

6. 数据模型

6.1 请求数据模型

ChatRequest - 聊天请求
csharp 复制代码
public class ChatRequest
{
    [JsonProperty("model")]
    public string model { get; set; }  // 模型名称

    [JsonProperty("messages")]
    public List<Message> messages { get; set; }  // 消息列表

    [JsonProperty("temperature", NullValueHandling = NullValueHandling.Ignore)]
    public double? temperature { get; set; }  // 温度参数(0-2)

    [JsonProperty("max_tokens", NullValueHandling = NullValueHandling.Ignore)]
    public int? max_tokens { get; set; }  // 最大token数

    [JsonProperty("top_p", NullValueHandling = NullValueHandling.Ignore)]
    public double? top_p { get; set; }  // 核采样参数

    [JsonProperty("stream", NullValueHandling = NullValueHandling.Ignore)]
    public bool? stream { get; set; }  // 是否流式输出
}
Message - 消息
csharp 复制代码
public class Message
{
    [JsonProperty("role")]
    public string role { get; set; }  // 角色: system/user/assistant

    [JsonProperty("content")]
    public string content { get; set; }  // 消息内容
}

6.2 响应数据模型

ChatResponse - 聊天响应
csharp 复制代码
public class ChatResponse
{
    [JsonProperty("id")]
    public string id { get; set; }  // 响应ID

    [JsonProperty("object")]
    public string @object { get; set; }  // 对象类型

    [JsonProperty("created")]
    public long created { get; set; }  // 创建时间戳

    [JsonProperty("model")]
    public string model { get; set; }  // 使用的模型

    [JsonProperty("choices")]
    public List<Choice> choices { get; set; }  // 选择列表

    [JsonProperty("usage")]
    public Usage usage { get; set; }  // Token使用情况

    [JsonProperty("error")]
    public ErrorInfo error { get; set; }  // 错误信息
}
Choice - 选择项
csharp 复制代码
public class Choice
{
    [JsonProperty("index")]
    public int index { get; set; }  // 索引

    [JsonProperty("message")]
    public Message message { get; set; }  // AI回复消息

    [JsonProperty("finish_reason")]
    public string finish_reason { get; set; }  // 结束原因
}
Usage - Token使用情况
csharp 复制代码
public class Usage
{
    [JsonProperty("prompt_tokens")]
    public int prompt_tokens { get; set; }  // 输入token数

    [JsonProperty("completion_tokens")]
    public int completion_tokens { get; set; }  // 输出token数

    [JsonProperty("total_tokens")]
    public int total_tokens { get; set; }  // 总token数
}

7. 常见问题

7.1 认证失败 (401)

错误现象: HTTP错误: 401 - Unauthorized

原因:

  • Token无效或过期
  • Token格式不正确

解决方案:

csharp 复制代码
// 确保Token格式正确
api.SetToken("your-actual-token-here");

// 检查Token是否有效

7.2 请求超时

错误现象: 请求超时异常

解决方案:

csharp 复制代码
// 在WebApiHelper中已设置60秒超时
private static HttpClient _httpClient = new HttpClient()
{
    Timeout = TimeSpan.FromSeconds(60)
};

7.3 JSON解析错误

错误现象: JSON解析错误: ...

原因:

  • 返回的JSON格式不正确
  • 模型定义与响应不匹配

解决方案:

csharp 复制代码
// 先查看原始响应
Console.WriteLine(response.Content);

// 检查模型属性名是否匹配(区分大小写)
[JsonProperty("model")]  // 必须与API返回的字段名一致
public string model { get; set; }

7.4 异步调用死锁

错误现象: UI界面卡死

原因 : 在WinForms中使用 .Result.Wait() 可能导致死锁

解决方案:

csharp 复制代码
// ✗ 错误写法(可能导致死锁)
var result = api.SendChatAsync(question).Result;

// ✓ 正确写法
private async void btnSend_Click(object sender, EventArgs e)
{
    var result = await api.SendChatAsync(question);
}

附录 A: 配置文件

App.config

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
  </startup>

  <appSettings>
    <!-- DeepSeek API 配置 -->
    <add key="DeepSeekBaseUrl" value="https://xxx.cn-xxx.xxx.com"/>
    <add key="DeepSeekToken" value="your-token-here"/>
    <add key="DeepSeekModel" value="deepseek-v3-250324"/>
    <!-- 请求超时时间(毫秒) -->
    <add key="RequestTimeout" value="60000"/>
  </appSettings>
</configuration>

附录 B: 快速参考

HTTP状态码

状态码 含义 说明
200 OK 请求成功
400 Bad Request 请求参数错误
401 Unauthorized 认证失败
429 Too Many Requests 请求过于频繁
500 Internal Server Error 服务器错误

WebApiHelper 方法速查

方法 说明 是否需要Token
HttpPost<T>() 发送JSON
HttpPostAsync<T>() 异步发送JSON
HttpPostBearerToken<T>() 带Token发送JSON
HttpPostBearerTokenAsync<T>() 异步带Token发送JSON
HttpPost() 发送表单
HttpGet() GET请求
HttpGetAsync() 异步GET请求
HttpGetBearerToken() 带Token的GET请求

相关推荐
yuan199973 小时前
C# 断点续传下载文件工具设计与实现
开发语言·c#
雨浓YN5 小时前
WebApi 通讯-自写Demo技术文档
c#
唐青枫5 小时前
C#.NET TPL Dataflow 深入解析:数据流管道、背压控制与实战取舍
c#·.net
喵叔哟6 小时前
4.【.NET10 实战--孢子记账--产品智能化】--C# 14 新语法特性详解与实战应用
java·c#·.net
Khsc434ka6 小时前
.NET 10 与智能体时代的架构演进:以 File-Based Apps 为核心的 C# 生态重塑
架构·c#·.net
jackylzh6 小时前
C# 中 LINQ 和 Lambda 表达式的 基本用法
c#
lzhdim7 小时前
C#中加载图片的资源释放
开发语言·c#
山檐雾1 天前
OctreeNode
unity·c#·八叉树