golangAPI调用deepseek

目录

  • 1.deepseek官方API调用文档
    • 1.访问格式
    • 2.curl组装
  • 2.go代码
      • 1. config 配置
      • 2.模型相关
      • 3.错误处理
      • 4.deepseekAPI接口实现
      • 5. 调用使用
  • 3.响应实例

1.deepseek官方API调用文档

1.访问格式

在这里插入图片描述
现在我们来解析这个curl

2.curl组装

// 这是请求头要加的参数
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <DeepSeek API Key>" \

// 这是请求体要加的参数
-d '{
        "model": "deepseek-chat",
        "messages": [
          {"role": "system", "content": "You are a helpful assistant."},
          {"role": "user", "content": "Hello!"}
        ],
        "stream": false
      }'

这个里面可以看出,user角色使我们要输入的问题,stream选择是否为流式响应

2.go代码

1. config 配置

type Config struct {
	BaseURL    string
	APIKey     string
	HTTPClient *http.Client
}

2.模型相关

type Model interface {
	Chat(ctx context.Context, req Request) (*Response, error)
	Stream(ctx context.Context, req Request) (<-chan Response, error)
}

type Request struct {
	Model    string    `json:"model"`
	Messages []Message `json:"messages"`
	Stream   bool      `json:"stream"`
}

type Message struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type Response struct {
	Content string `json:"content"`
}

3.错误处理

// Error 标准错误类型
type Error struct {
	Code    int
	Message string
	Model   string
}

func (e *Error) Error() string {
	return fmt.Sprintf("[%s] %d: %s", e.Model, e.Code, e.Message)
}

4.deepseekAPI接口实现

type DeepSeek struct {
	Cfg ai.Config
}

func NewDeepSeek(cfg ai.Config) *DeepSeek {
	return &DeepSeek{Cfg: cfg}
}

func (d *DeepSeek) Stream(ctx context.Context, request ai.Request) (<-chan ai.Response, error) {
	return d.handleStreaming(ctx, request)
}

func (d *DeepSeek) Chat(ctx context.Context, request ai.Request) (*ai.Response, error) {
	doRequest, err := d.doRequest(ctx, request, false)
	if err != nil {
		return nil, err
	}
	return d.parseResponse(doRequest)
}

func (d *DeepSeek) parseResponse(resp *http.Response) (*ai.Response, error) {
	all, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("io.ReadAll failed, err: %v\n", err)
	}
	defer resp.Body.Close()
	return &ai.Response{Content: string(all)}, nil
}

// 私有方法
func (d *DeepSeek) doRequest(ctx context.Context, req ai.Request, stream bool) (*http.Response, error) {
	req.Stream = stream
	body, _ := json.Marshal(req)

	httpReq, err := http.NewRequestWithContext(
		ctx,
		"POST",
		d.Cfg.BaseURL+"/chat/completions",
		bytes.NewReader(body),
	)
	// 设置请求头
	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Authorization", "Bearer "+apiKey)
	resp, err := d.Cfg.HTTPClient.Do(httpReq)
	if err != nil {
		return nil, &ai.Error{
			Model:   "deepseek",
			Code:    http.StatusInternalServerError,
			Message: fmt.Sprintf("HTTP error: %v", err),
		}
	}

	if resp.StatusCode != http.StatusOK {
		return nil, &ai.Error{
			Model:   "deepseek",
			Code:    http.StatusInternalServerError,
			Message: fmt.Sprintf("failed to request: %v", err),
		}
	}
	return resp, nil
}

func (d *DeepSeek) handleStreaming(ctx context.Context, req ai.Request) (<-chan ai.Response, error) {
	ch := make(chan ai.Response)
	go func() {
		defer close(ch)
		// 发起流式请求
		resp, err := d.doRequest(ctx, req, true)
		if err != nil {
			ch <- ai.Response{Content: "request error!"}
			return
		}
		defer resp.Body.Close()

		scanner := bufio.NewScanner(resp.Body)
		for scanner.Scan() {
			select {
			case <-ctx.Done():
				ch <- ai.Response{Content: "ctx done!"}
				return
			default:
				// 解析事件流
				event := parseEvent(scanner.Bytes())
				if event != nil {
					ch <- *event
				}
			}
		}
	}()

	return ch, nil
}

func parseEvent(line []byte) *ai.Response {
	// 处理事件流格式
	if !bytes.HasPrefix(line, []byte("data: ")) {
		return nil
	}

	payload := bytes.TrimPrefix(line, []byte("data: "))
	if string(payload) == "[DONE]" {
		return nil
	}

	// 解析响应结构
	var chunk struct {
		Choices []struct {
			Delta struct {
				Content string `json:"content"`
			}
			FinishReason string `json:"finish_reason"`
		}
	}

	if err := json.Unmarshal(payload, &chunk); err != nil {
		return nil
	}

	if len(chunk.Choices) > 0 {
		content := chunk.Choices[0].Delta.Content
		finishReason := chunk.Choices[0].FinishReason

		if content != "" {
			return &ai.Response{Content: content}
		}

		if finishReason == "stop" {
			return nil
		}
	}
	return nil
}

5. 调用使用

func main() {
	cfg := ai.Config{
		BaseURL:    "https://api.deepseek.com/",
		APIKey:     "key",
		HTTPClient: &http.Client{},
	}

	// 初始化deepseek
	d := deepseek.NewDeepSeek(cfg)

	// 封装请求体
	body := ai.Request{
		Model:    "deepseek-chat",
		Messages: []ai.Message{{Role: "system", Content: "You are a helpful assistant."}, {Role: "user", Content: "你是谁"}},
	}

	// 同步调用
	chat, err := d.Chat(context.Background(), body)
	if err != nil {
		panic(err)
	}
	fmt.Println(chat.Content)

	// 流式调用
	stream, _ := d.Stream(context.Background(), body)
	for chunk := range stream {
		fmt.Printf(chunk.Content)
	}
}

3.响应实例

// 同步
{"id":"","object":"chat.completion","created":,"model":"deepseek-chat","choices":[{"index":0,"message":{"role":"assistant","content":"您好!我是由中国的深度求索(DeepSeek)公司开发的何任何问题,我会尽我所能为您提供帮助。"},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"completion_tokens":37,"total_tokens":47,"prompt_tokens_details":{"cached_tokens":0},"prompt_cache_hit_tokens":0,"proms":10},"system_fingerprint":"fp_3a5770e1b4"}


// 流式
您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-V3。如您有任何任何问题,我会尽我所能为您提供帮助。

代码地址:https://gitee.com/li-zhuoxuan/go_ai

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/971732.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

闭源大语言模型的怎么增强:提示工程 检索增强生成 智能体

闭源大语言模型的怎么增强 提示工程 检索增强生成 智能体 核心原理 提示工程:通过设计和优化提示词,引导大语言模型进行上下文学习和分解式思考,激发模型自身的思维和推理能力,使模型更好地理解和生成文本,增强其泛用性和解决问题的能力。检索增强生成:结合检索的准确…

《计算机视觉》——角点检测和特征提取sift

角点检测 角点的定义&#xff1a; 从直观上理解&#xff0c;角点是图像中两条或多条边缘的交点&#xff0c;在图像中表现为局部区域内的灰度变化较为剧烈的点。在数学和计算机视觉中&#xff0c;角点可以被定义为在两个或多个方向上具有显著变化的点。比如在一幅建筑物的图像…

具身智能在智能巡检机器人中的应用——以开关柜带电操作机器人为例

随着机器人技术和人工智能的迅速发展&#xff0c;具身智能在各行业的应用日益广泛&#xff0c;尤其是在电力行业中的智能巡检领域。传统的电力巡检和维护工作通常需要人工操作&#xff0c;存在着高温、高压、强电磁场等危险环境&#xff0c;且效率较低。开关柜带电操作机器人作…

基于SpringBoot实现的大学社团平台系统实现功能八

一、前言介绍&#xff1a; 1.1 项目摘要 随着高校社团活动的日益丰富和多样化&#xff0c;学生对于社团管理和参与的需求也在不断增加。传统的社团管理方式往往存在效率低下、信息不透明等问题&#xff0c;无法满足现代学生对于便捷、高效社团管理的需求。因此&#xff0c;利…

Unity使用反射进行Protobuf(CS/SC)协议,json格式

protobuf生成的协议,有挺多协议的.利用反射生成dto进行伪协议的响应 和 发送请求 应用场景: 请求(CS)_后端先写完了(有proto接口了),前端还没搞完时(暂还没接入proto),后端可使用此请求,可自测 响应(SC)_可自行构建一个响应(有些特殊数据后端下发不了的),对数据进行测试 // 请…

使用synchronized解决高并发场景

synchronized能很好的解决高并发所带来的超卖等问题&#xff0c;但是synchronized也有属于它的缺陷&#xff0c;就是只适合单机模式&#xff0c;如果同时开启多个实例&#xff0c;那么还是会出现超卖的情况&#xff0c;下面就介绍一下synchronized使用方法&#xff0c;十分的简…

【Pytorch 库】自定义数据集相关的类

torch.utils.data.Dataset 类torch.utils.data.DataLoader 类自定义数据集示例1. 自定义 Dataset 类2. 在其他 .py 文件中引用和使用该自定义 Dataset torch_geometric.data.Dataset 类torch_geometric.data.Dataset VS torch.utils.data.Dataset 详细信息&#xff0c;参阅 tor…

Softing线上研讨会 | 自研还是购买——用于自动化产品的工业以太网

| 线上研讨会时间&#xff1a;2025年1月27日 16:00~16:30 / 23:00~23:30 基于以太网的通信在工业自动化网络中的重要性日益增加。设备制造商正面临着一大挑战——如何快速、有效且经济地将工业以太网协议集成到其产品中。其中的关键问题包括&#xff1a;是否只需集成单一的工…

Wireshark 输出 数据包列表本身的值

在 Wireshark 中&#xff0c;如果你想输出数据包列表本身的值&#xff08;例如&#xff0c;将数据包的摘要信息、时间戳、源地址、目的地址等导出为文本格式&#xff09;&#xff0c;可以使用 导出为纯文本文件 的功能。以下是详细步骤&#xff1a; 步骤 1&#xff1a;打开 Wir…

解压rar格式的软件有哪些?8种方法(Win/Mac/手机/网页端)

RAR 文件是一种常见的压缩文件格式&#xff0c;由尤金・罗谢尔&#xff08;Eugene Roshal&#xff09;开发&#xff0c;因其扩展名 “rar” 而得名。它通过特定算法将一个或多个文件、文件夹进行压缩&#xff0c;大幅减小存储空间&#xff0c;方便数据传输与备份。然而&#xf…

java实现不带哨兵节点的双向链表(二)

概述 todo 扩展&#xff1a;实现链表节点的删除&#xff08;根据索引删除节点、删除第一个元素&#xff09;、添加的元素为数组最后一个元素&#xff08;addLast&#xff09;等 实现上一篇博客中提到的 根据索引删除节点。删除第一个元素。添加的元素为数组最后一个元素。 根…

AcWing 798. 差分矩阵

题目来源&#xff1a; 找不到页面 - AcWing 题目内容&#xff1a; 输入一个 n 行 m 列的整数矩阵&#xff0c;再输入 q 个操作&#xff0c;每个操作包含五个整数 x1,y1,x2,y2,c&#xff0c;其中 (x1,y1) 和 (x2,y2)表示一个子矩阵的左上角坐标和右下角坐标。 每个操作都要将…

【kafka系列】消费者

目录 获取消息 1. 消费者获取消息的流程逻辑分析 阶段一&#xff1a;消费者初始化 阶段二&#xff1a;分区分配与重平衡&#xff08;Rebalance&#xff09; 阶段三&#xff1a;消息拉取与处理 阶段四&#xff1a;偏移量提交 核心设计思想 2. 流程 关键点总结 常见参数…

游戏引擎学习第105天

仓库:https://gitee.com/mrxiao_com/2d_game_2 查看当前进度 今天的工作重点是继续进行渲染系统的清理。昨天已经完成了一次渲染清理&#xff0c;现在还有一些内容需要继续处理。首先&#xff0c;已经解决了坐标系统的问题&#xff0c;其中世界坐标基本上是正确的&#xff0c…

重新求职刷题力扣DAY15

1.[226. 翻转二叉树](https://leetcode.cn/problems/symmetric-tree/) 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a…

OpenGL ES -> 投影变换矩阵完美解决绘制GLSurfaceView绘制图形拉伸问题

GLSurfaceView绘制图形拉伸问题 假如在XML文件中声明GLSurfaceView的宽高为 android:layout_width"match_parent"android:layout_height"match_parent GLSurfaceView绘制的图形在Open GL ES坐标系中&#xff0c;而Open GL ES坐标系会根据GLSurfaceView的宽高将…

Java并发编程8--线程

1.什么是线程&#xff1f; 现代操作系统调度的最小单元是线程&#xff0c;也叫轻量级进程&#xff08;Light Weight Process&#xff09;&#xff0c;在一个进程里可以创建多个线程&#xff0c;这些线程都拥有各自的计数器、堆栈和局部变量等属性&#xff0c;并且能够访问共享的…

java八股文-mysql

1. 索引 1.1 什么是索引 索引(index)是帮助Mysql高效获取数据的数据结构(有序).提高数据的检索效率,降低数据库的IO成本(不需要全表扫描).通过索引列对数据进行排序,降低数据排序成本,降低了CPU的消耗. 1.2 mysql索引使用的B树? 1. 没有使用二叉树&#xff0c;最坏情况o&…

开启蓝耘之旅:DeepSeek R1 模型在智算平台的起步教程

----------------------------------------------------------我的个人主页-------------------- 动动你的手指----------------------------------------点赞&#x1f44d; 收藏❤--------------------------------------------------------------- 引言 在深度学习的广袤领…

【设计模式】【行为型模式】访问者模式(Visitor)

&#x1f44b;hi&#xff0c;我不是一名外包公司的员工&#xff0c;也不会偷吃茶水间的零食&#xff0c;我的梦想是能写高端CRUD &#x1f525; 2025本人正在沉淀中… 博客更新速度 &#x1f44d; 欢迎点赞、收藏、关注&#xff0c;跟上我的更新节奏 &#x1f3b5; 当你的天空突…