不用第三方库调用DeepSeek
又双叒叕很久不写博客,今天吐一口老曹。
一、为啥干这个
之前在修改OJ的时候,本着少修改多收益的原则,用Python写了一些DeepSeek的调用,真的很简单,用拉下来OpenAI按照官方文档复制粘贴就可以。接口文档页面(首次调用 API | DeepSeek API Docs)上至今有三种:curl(哦天哪,我在捣鼓ubuntu的时候好像用这个)、python(这个看着脸熟……当时敲的就是,那没事了)、node.js(dot是后加的,不然还真不认识)。
但是,随着需求越搞越多,顺手就祭起冷门编程语言VB.NET了。完成了各种远程多Judge服务器之后,发现".py"越看越不顺眼。于是乎,来吧NuGet一下……emmmmm……两下、三四五六下,He,Tui~~~
然后,再次祭起冷门语言VB.NET。因为之前就是多线程在搞一些队列呀、JudgeAPI呀,所以这个线程突然就顺手了。众所周知,我也不知道到底OpenAI支持多少参数,咱也搜不到,咱也不敢搜。所以,就比着能找到的就行了。并且,为了凑字数,成员定义的非常啰嗦:
Imports System
Imports System.Net.Http
Imports System.Text
Imports System.Threading.Tasks
Imports System.Text.Json
Imports System.Text.Json.Serialization
Imports System.Net
Imports System.ThreadingPublic Class DeepSeekClientPrivate ReadOnly _sharedHttpClient As HttpClientPrivate ReadOnly _apiKey As StringPrivate ReadOnly _apiBaseUrl As StringPrivate _model As String = "deepseek-chat"Private _temperature As Single = 0.1Private _maxTokens As Integer = 2048Private _top_p As Single = 0.2Private _stream As Boolean = False''' <summary>''' 初始化 DeepSeek 客户端(使用共享 HttpClient)''' </summary>''' <param name="sharedHttpClient">共享的 HttpClient 实例</param>''' <param name="apiKey">API 密钥</param>''' <param name="apiBaseUrl">API 基础地址 (可选,默认为官方地址)</param>Public Sub New(sharedHttpClient As HttpClient, apiKey As String, Optional apiBaseUrl As String = "https://api.deepseek.com/")If sharedHttpClient Is Nothing ThenThrow New ArgumentNullException(NameOf(sharedHttpClient))End IfIf String.IsNullOrWhiteSpace(apiKey) ThenThrow New ArgumentException("APIKey不能为空。", NameOf(apiKey))End If_sharedHttpClient = sharedHttpClient_apiKey = apiKey_apiBaseUrl = apiBaseUrl.TrimEnd("/"c)' 如果 HttpClient 还没有 Authorization 头,则添加If Not _sharedHttpClient.DefaultRequestHeaders.Contains("Authorization") Then_sharedHttpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}")End IfEnd Sub''' <summary>''' 设置模型名称''' </summary>Public Property Model As StringGetReturn _modelEnd GetSet(value As String)If String.IsNullOrWhiteSpace(value) ThenThrow New ArgumentException("模型名称不能为空。")End If_model = valueEnd SetEnd Property''' <summary>''' 设置温度参数 (0-2)''' </summary>Public Property Temperature As SingleGetReturn _temperatureEnd GetSet(value As Single)If value < 0 OrElse value > 2 ThenThrow New ArgumentOutOfRangeException(NameOf(Temperature), "温度值应在[0,2]区间")End If_temperature = valueEnd SetEnd Property''' <summary>''' 设置最大令牌数''' </summary>Public Property MaxTokens As IntegerGetReturn _maxTokensEnd GetSet(value As Integer)If value <= 0 ThenThrow New ArgumentOutOfRangeException(NameOf(MaxTokens), "最大Token数不应小于0。")End If_maxTokens = valueEnd SetEnd Property''' <summary>''' 生成多样性控制''' </summary>Public Property Top_p As SingleGetReturn _top_pEnd GetSet(value As Single)If value < 0 OrElse value > 1 ThenThrow New ArgumentOutOfRangeException(NameOf(Temperature), "Top_p应在[0,1]区间。")End If_top_p = valueEnd SetEnd Property''' <summary>''' 是否流式响应''' </summary>Public Property Stream As BooleanGetReturn _streamEnd GetSet(value As Boolean)_stream = valueEnd SetEnd Property''' <summary>''' 发送消息到 DeepSeek API 并获取响应''' </summary>''' <param name="userMessage">用户消息内容</param>''' <returns>API 响应内容</returns>Public Async Function SendMessageAsync(systemMessage As String, userMessage As String, timeout As TimeSpan) As Task(Of String)If String.IsNullOrWhiteSpace(systemMessage) ThenThrow New ArgumentException("系统消息不能为空。", NameOf(systemMessage))End IfIf String.IsNullOrWhiteSpace(userMessage) ThenThrow New ArgumentException("用户消息不能为空。", NameOf(userMessage))End IfIf timeout = Nothing ThenThrow New ArgumentException("超时时间不能为空。", NameOf(timeout))End If' 创建请求体对象Dim requestBody = New DeepSeekRequest With {.Model = _model,.Messages = New List(Of ChatMessage) From {New ChatMessage With {.Role = "system", .Content = systemMessage},New ChatMessage With {.Role = "user", .Content = userMessage}},.Temperature = _temperature,.MaxTokens = _maxTokens,.Top_p = Top_p,.Stream = False}' 使用 System.Text.Json 序列化Dim jsonContent = JsonSerializer.Serialize(requestBody)Dim content = New StringContent(jsonContent, Encoding.UTF8, "application/json")Try' 创建带有超时设置的请求Dim request = New HttpRequestMessage(HttpMethod.Post, $"{_apiBaseUrl}/chat/completions") With {.Content = content}' 使用 CancellationTokenSource 实现单次请求超时Using cts = New CancellationTokenSource(timeout)Dim response = Await _sharedHttpClient.SendAsync(request, cts.Token)Dim responseContent = Await response.Content.ReadAsStringAsync()If Not response.IsSuccessStatusCode ThenHandleApiError(response.StatusCode, responseContent)End If' 使用 System.Text.Json 反序列化Dim responseObject = JsonSerializer.Deserialize(Of DeepSeekResponse)(responseContent)Return responseObject?.Choices?.FirstOrDefault()?.Message?.ContentEnd UsingCatch ex As TaskCanceledException When Not ex.CancellationToken.IsCancellationRequestedThrow New TimeoutException("请求超时。", ex)Catch ex As OperationCanceledExceptionThrow New TimeoutException("由于超时,请求被取消。", ex)Catch ex As HttpRequestExceptionThrow New Exception("发送请求时出错。", ex)End TryEnd Function''' <summary>''' 处理 API 错误响应''' </summary>Private Sub HandleApiError(statusCode As HttpStatusCode, responseContent As String)Dim errorMessage As String = "发生未知错误"TryIf Not String.IsNullOrEmpty(responseContent) ThenDim errorResponse = JsonSerializer.Deserialize(Of DeepSeekErrorResponse)(responseContent)errorMessage = If(errorResponse?.Error?.Message, errorMessage)End IfCatch' 如果 JSON 解析失败,使用默认错误消息End TrySelect Case statusCodeCase HttpStatusCode.BadRequest ' 400Throw New DeepSeekApiException("错误请求:" & errorMessage, statusCode)Case HttpStatusCode.Unauthorized ' 401Throw New DeepSeekApiException("身份验证失败。请检查您的API密钥。", statusCode)Case HttpStatusCode.PaymentRequired ' 402Throw New DeepSeekApiException("余额不足。请给您的帐户充值。", statusCode)Case CType(422, HttpStatusCode) ' 422Throw New DeepSeekApiException("参数错误。" & errorMessage, statusCode)Case CType(429, HttpStatusCode) ' 429Throw New DeepSeekApiException("超出速率限制。请降低您的请求频率。", statusCode)Case HttpStatusCode.InternalServerError ' 500Throw New DeepSeekApiException("服务器错误。请稍后再试。", statusCode)Case HttpStatusCode.ServiceUnavailable ' 503Throw New DeepSeekApiException("服务器繁忙。请稍后再试。", statusCode)Case ElseThrow New DeepSeekApiException($"API 错误 ({statusCode}): {errorMessage}", statusCode)End SelectEnd Sub
End Class' 请求和响应数据模型
Public Class DeepSeekRequest<JsonPropertyName("model")>Public Property Model As String<JsonPropertyName("messages")>Public Property Messages As List(Of ChatMessage)<JsonPropertyName("temperature")>Public Property Temperature As Single<JsonPropertyName("top_p")>Public Property Top_p As Single<JsonPropertyName("max_tokens")>Public Property MaxTokens As Integer<JsonPropertyName("stream")>Public Property Stream As Boolean
End ClassPublic Class ChatMessage<JsonPropertyName("role")>Public Property Role As String<JsonPropertyName("content")>Public Property Content As String
End ClassPublic Class DeepSeekResponse<JsonPropertyName("choices")>Public Property Choices As List(Of Choice)
End ClassPublic Class Choice<JsonPropertyName("message")>Public Property Message As ChatMessage
End ClassPublic Class DeepSeekErrorResponse<JsonPropertyName("error")>Public Property [Error] As ApiError
End ClassPublic Class ApiError<JsonPropertyName("message")>Public Property Message As String<JsonPropertyName("type")>Public Property Type As String<JsonPropertyName("code")>Public Property Code As String
End Class''' <summary>
''' DeepSeek API 异常类
''' </summary>
Public Class DeepSeekApiExceptionInherits ExceptionPublic ReadOnly Property StatusCode As HttpStatusCodePublic Sub New(message As String, statusCode As HttpStatusCode)MyBase.New(message)Me.StatusCode = statusCodeEnd SubPublic Sub New(message As String, statusCode As HttpStatusCode, innerException As Exception)MyBase.New(message, innerException)Me.StatusCode = statusCodeEnd Sub
End Class
以上就是DeepSeek写的调用自己的代码(添加了几个属性、增加了几个参数、翻译了几段英文错误说明)之后的样子。
接下来就是调用咯:
' 全局共享的 HttpClientPrivate Shared ReadOnly HttpClientInstance As New HttpClient()Async Function TestDeepSeekClient(modeName As String, systemMessage As String, userMessage As String, timeOut As TimeSpan) As Task(Of (Boolean, String))Try' 初始化客户端(使用共享的 HttpClient)Dim apiKey = "sk-差点得去换APIKEY- -!!!"Dim client = New DeepSeekClient(HttpClientInstance, apiKey)' 自定义参数 (可选)client.Model = modeNameclient.Temperature = 0.1client.MaxTokens = 1024client.Top_p = 0.2client.Stream = False' 发送消息Dim response = Await client.SendMessageAsync(systemMessage, userMessage, timeOut)Return (True, response)Catch ex As DeepSeekApiExceptionReturn (False, $"API Error ({ex.StatusCode}): {ex.Message}")Catch ex As ExceptionReturn (False, $"Error: {ex.Message}")End TryEnd Function
最后,就是调用的调用:
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click'"deepseek-chat" "deepseek-reasoner"Dim result = Await TestDeepSeekClient("deepseek-chat", "你是一个AI。", "你的名字是?", TimeSpan.FromSeconds(600))If result.Item1 ThenDebug.Print(result.Item2)ElseDebug.Print("发生错误:" & result.Item2)End IfDebug.Print("完成。")End Sub
好了,到此为止吧。
相关文章:
不用第三方库调用DeepSeek
又双叒叕很久不写博客,今天吐一口老曹。 一、为啥干这个 之前在修改OJ的时候,本着少修改多收益的原则,用Python写了一些DeepSeek的调用,真的很简单,用拉下来OpenAI按照官方文档复制粘贴就可以。接口文档页面ÿ…...
Proximal Policy Optimization (PPO)
2.1 策略梯度方法 策略梯度方法计算策略梯度的估计值并将其插入到随机梯度上升算法中。最常用的梯度估计器的形式如下: g ^ E t [ ∇ θ log π θ ( a t ∣ s t ) A ^ t ] (1) \hat{g} \mathbb{E}_t \left[ \nabla_{\theta} \log \pi_{\theta}(a_t | s_t) \h…...
微信小程序:动态表格实现,表头单元格数据完全从data中获取,宽度自定义,自定义文本框,行勾选,样式效果,横向滚动表格(解决背景色不足的问题)等
一、样式效果 二、代码 1、wxml <view class"line flex flex-center"><view class"none" wx:if"{{info.length 0}}">暂无料号</view><view wx:else class"table-container"><!-- 动态生成表头 -->&…...
Java基础编程练习第38题-除法器
题目:编写一个除法器,输入被除数和除数,并将结果输出。 这道题看似很简单,实则也不难。 就是假如用户输入的类型不同怎么办呢?用户输入int或者double类型应该怎么解决。这里我们就需要用到函数的重载。 代码如下&am…...
fabric.js基础使用
1.正方形 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Fabric.js Watermark Example</tit…...
python-Leetcode 65.搜索旋转排序数组
题目: 整数数组nums按升序排列,数组中的值互不相同 在传递给函数之前,nums在预先未知的某个小标K上进行了旋转,使数组变为[nums[k], nums[k1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]],小标从0开始计数。…...
质数质数筛
1.试除法判定质数–O(sqrt(N)) bool is_prime(int x) {if (x < 2) return false;for (int i 2; i < x / i; i )if (x % i 0)return false;return true; }2.试除法分解质因数–O(logN)~O(sqrt(N)) void divide(int x) {for (int i 2; i < x / i; i )if (x % i …...
Django学习记录-1
Django学习记录-1 虽然网上教程都很多,但是感觉自己记录一下才属于自己,之后想找也方面一点,文采不佳看的不爽可绕道。 参考贴 从零开始的Django框架入门到实战教程(内含实战实例) - 01 创建项目与app、加入静态文件、模板语法介绍ÿ…...
K8s私有仓库拉取镜像报错解决:x509 certificate signed by unknown authority
前言 在Kubernetes环境中使用自签名证书的私有Harbor镜像仓库时,常会遇到证书验证失败的问题。本文将详细讲解如何解决这个常见的证书问题。 环境信息: Kubernetes版本:1.28.2容器运行时:containerd 1.6.20私有仓库:…...
使用python访问mindie部署的vl多模态模型
说明 今天使用mindie1.0部署了qwen2_7b_vl模型,测试过程出现一些问题,这里总结下。 问题1:transformers版本太低 报错信息: [ERROR] [model_deploy_config.cpp:159] Failed to get vocab size from tokenizer wrapper with ex…...
LabVIEW 长期项目开发
LabVIEW 凭借其图形化编程的独特优势,在工业自动化、测试测量等领域得到了广泛应用。对于长期运行、持续迭代的 LabVIEW 项目而言,其开发过程涵盖架构设计、代码管理、性能优化等多个关键环节,每个环节都对项目的成功起着至关重要的作用。下面…...
MongoDB 的详细介绍
以下是 MongoDB 的详细介绍,涵盖核心概念、使用场景、优势与操作示例: 一、MongoDB 简介 MongoDB 是一个开源的 文档型 NoSQL 数据库,采用灵活的 JSON-like(BSON)格式存储数据,适合处理非结构化或半结构化数据。 核心特点: Schema-free:无需预定义表结构,字段可动态扩…...
Ubuntu 22.04 AI大模型环境配置及常用工具安装
一、基础环境准备 1.1 系统准备 建议使用 Ubuntu22.04 以下配置皆以 Ubuntu22.04 系统版本为例 1.2 安装git apt-get update && apt-get install git -y1.3 安装 Python 3.9 【建议安装 3.10】(安装miniconda或者conda来管理虚拟环境) wget …...
蓝桥杯真题——好数、R格式
目录 蓝桥杯2024年第十五届省赛真题-好数 【模拟题】 题目描述 输入格式 输出格式 样例输入 样例输出 提示 代码1:有两个案例过不了,超时 蓝桥杯2024年第十五届省赛真题-R 格式 【vector容器的使用】 题目描述 输入格式 输出格式 样例输入…...
AWS S3深度剖析:云存储的瑞士军刀
1. 引言 在当今数据驱动的世界中,高效、可靠、安全的数据存储解决方案至关重要。Amazon Simple Storage Service (S3)作为AWS生态系统中的核心服务之一,为企业和开发者提供了一个强大而灵活的对象存储平台。本文将全面解析S3的核心特性,帮助读者深入理解如何充分利用这一&q…...
Qt基础:右键菜单
右键菜单 1. 基于鼠标事件实现1.1 原理1.2 操作 2. 基于窗口的菜单策略实现2.1 Qt::DefaultContextMenu2.2 Qt::ActionsContextMenu 2.3 Qt::CustomContextMenu 显示右键菜单, 其处理方式大体上有两种: 基于鼠标事件实现;基于窗口的菜单策略实现。 1. …...
Json快速入门
引言 Jsoncpp 库主要是用于实现 Json 格式数据的序列化和反序列化,它实现了将多个数据对象组织成 为Json格式字符串,以及将 Json 格式字符串解析得到多个数据对象的功能,独立于开发语言。 Json数据对象 Json数据对象类的表示: …...
WinForm真入门(10)——CheckBox控件详解
在 WinForm 中,CheckBox 控件是一个用于表示布尔状态(选中/未选中)的核心组件。它广泛应用于配置选项、表单提交、条件筛选等场景。以下是 CheckBox 的详细解析,涵盖属性、事件、使用技巧和实际案例。 一、CheckBox 核心属性…...
网络安全应急响应-系统排查
在网络安全应急响应中,系统排查是快速识别潜在威胁的关键步骤。以下是针对Windows和Linux系统的系统基本信息排查指南,涵盖常用命令及注意事项: 一、Windows系统排查 1. 系统信息工具(msinfo32.exe) 命令执行&#x…...
[QMT量化交易小白入门]-四十二、五年年化收益率26%,当日未成交的下单,取消后重新委托
本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。 QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。 文章目录 相关阅读委托查询功能3.1 数据获取层3.2 数据结构初始…...
Windows版-RabbitMQ自动化部署
一键完成Erlang环境变量配置(ERLANG_HOME系统变量) 一键完成RabbitMQ环境变量配置(RabbitMQ系统变量) 实现快速安装部署RabbitMQ PS: 需提前下载安装: - otp_win64_25.0.exe (Erlang) - rabbit…...
openEuler24.03 LTS下安装Flink
目录 Flink的安装模式下载Flink安装Local模式前提条件解压安装包启动集群查看进程提交作业文件WordCount持续流WordCount 查看Web UI配置flink-conf.yaml简单使用 关闭集群 Standalone Session模式前提条件Flink集群规划解压安装包配置flink配置flink-conf.yaml配置workers配置…...
LeetCode热题100记录-【二分查找】
二分查找 35.搜索插入位置 思考:二分查找先判定边界条件 记录:不需要二刷 class Solution {public int searchInsert(int[] nums, int target) {int left 0,right nums.length-1;if(nums[right] < target){return right1;}if(nums[left] > tar…...
从零开始学java--泛型(1)
泛型 学生成绩可能是数字类型,也可能是字符串类型,如何存放可能出现的两种类型呢: public class Score {String name;String id;Object value; //因为Object是所有类型的父类,因此既可以存放Integer也能存放Stringpublic Score…...
【正点原子】STM32MP135去除SD卡引脚复用,出现 /dev/mmcblk1p5 not found!
如果在设备树中直接注释掉 sdmmc1 节点,就会导致系统启动时识别不到真正的 eMMC 设备,进而挂载失败,爆出 /dev/mmcblk1p5 not found 的问题。 正点原子STM32MP135开发板Linux核心板嵌入式ARM双千兆以太网CAN 正确操作是“放空”而不是“删光…...
CrystalDiskInfo电脑硬盘监控工具 v9.6.0中文绿色便携版
前言 CrystalDiskInfo是一个不用花钱的硬盘小帮手软件,它可以帮你看看你的电脑硬盘工作得怎么样,健不健康。这个软件能显示硬盘的温度高不高、还有多少地方没用、传输东西快不快等等好多信息。用了它,你就能很容易地知道硬盘现在是什么情况&…...
详解模型蒸馏,破解DeepSeek性能谜题
大家好,不少关注 DeepSeek 最新动态的朋友,想必都遇到过 “Distillation”(蒸馏)这一术语。本文将介绍模型蒸馏技术的原理,同时借助 TensorFlow 框架中的实例进行详细演示。通过本文,对模型蒸馏有更深的认识…...
⭐算法OJ⭐数据流的中位数【最小堆】Find Median from Data Stream
最小堆 最小堆是一种特殊的完全二叉树数据结构。 基本定义 堆性质:每个节点的值都小于或等于其子节点的值(根节点是最小值)完全二叉树性质:除了最底层外,其他层的节点都是满的,且最底层的节点都靠左排列…...
园区网拓扑作业
作业要求: 需求: 需求分析: 1.按照图示的VLAN及IP地址需求,完成相关配需:VLAN 2、3、20、30 已分配子网,需在交换机上创建 VLAN 并配置三层接口作为网关。确保各 VLAN 内设备能互通,跨 VLAN 通…...
隔行换色总结
功能效果展示: 第一种思路: 使用数组,将数组的内容渲染到页面上,序号也就是将数组的下标输出到第一个td上,将数组的内容输出到第二个td上,(使用拼接字符串) 具体操作: …...
