1-原生go调用大模型

0 阅读5分钟

这边我选择deepseek练手

image.png

image.png

  • 分析上面的图
  • 这是一个post请求
    • model: 是请求的哪个模型
    • message: 就是请求的内容,包含 角色 以及 角色说的话术
      • system:是一个大的背景介绍(前提),比如 你是一个前端专家
      • user:用户
      • assistant: 大模型
      • 如果需要记住前面的内容,就需要把大模型上次说的也传入message(费token)
    • stream: 是否开启流式,非流式就是一次性给你
  • 请求的 urlhttps://api.deepseek.com/chat/completions
  • 还需要携带2个请求头, DEEPSEEK_API_KEY就是我们第一张图的apikey
  • 注意:

    • message中记录的越多(请求体)就越费钱
    • 大模型返回的数据越多也越费钱
    • 如果不想大模型返回过多,调用模型时候可以控制参数,比如温度
      • 温度越低大模型就更加冷静更加聚焦,返回的内容更少也更精准
    • 也可以限制 MaxToken,每次返回的token的个数上线
  • 例子1如下:

package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"

	"agent/config"

	"github.com/bytedance/sonic"
)

const DeepseekUrl = "https://api.deepseek.com/chat/completions" // API地址

// 定义message结构体
type Message struct {
	Role    string `json:"role"`    // 角色"system", "user", "assistant"
	Content string `json:"content"` // 内容
}

// 定义请求体结构体
type RequestBody struct {
	Model    string     `json:"model"`    // 模型名称
	Messages []*Message `json:"messages"` // 消息列表
	Stream   bool       `json:"stream"`   // 是否流式返回
}


func chatWithDeepseek(rb *RequestBody) {
	bs, err := sonic.Marshal(rb) // 转成json
	if err != nil {
		log.Printf("json序列化失败: %s", err)
		return
	}
	// 发送请求 bytes.NewReader(bs) 是请求体
	rq, _ := http.NewRequest(http.MethodPost, DeepseekUrl, bytes.NewReader(bs))
	// 添加请求头
	rq.Header.Add("Content-Type", "application/json")
	// 添加授权(鉴权)
	rq.Header.Add("Authorization", fmt.Sprintf("Bearer %s", config.APIKEY)) // 这里的key不做展示了
	client := http.Client{
		Timeout: 30 * time.Second, // 设置超时时间
	} // 创建http客户端
	resp, err := client.Do(rq) // 发送请求
	if err != nil {
		log.Printf("请求失败: %s", err)
		return
	}
	defer resp.Body.Close() // 关闭连接

	if resp.StatusCode != http.StatusOK {
		// 状态码不为200,则请求失败
		_, _ = io.Copy(os.Stdout, resp.Body) // 打印返回内容
		return
	}
	// 请求成功,读取返回内容
	bs, _ = io.ReadAll(resp.Body) //读取返回内容
	fmt.Println(string(bs))

}

func main() {
  rb := &RequestBody{
    Model: "deepseek-chat",
    Messages: []*Message{
      {
	Role:    "system",
	Content: "",
      },
      {
	Role:    "user",
	Content: "离五一放假还有几天?",
        // 再加上后面这段 "今天是2026年3月3号,离五一放假还有几天?"
      },
    },
    Stream: false, // 是否流式返回
  }
  chatWithDeepseek(rb)
}
  • 返回结果如下 image.png

  • 给出了日期的准了

    • 当大模型提示不准的时候,就需要人去给它更多限定条件,使它精准
    • prompt工程师(简称ai铲屎官) image.png
  • 你会发现这一堆返回有点杂,我们需要去提取我们要的信息

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"

	"agent/config"

	"github.com/bytedance/sonic"
)

const DeepseekUrl = "https://api.deepseek.com/chat/completions" // API地址

// 定义message结构体
type Message struct {
	Role    string `json:"role"`    // 角色"system", "user", "assistant"
	Content string `json:"content"` // 内容
}

// 定义请求体结构体
type RequestBody struct {
	Model    string     `json:"model"`    // 模型名称
	Messages []*Message `json:"messages"` // 消息列表
	Stream   bool       `json:"stream"`   // 是否流式返回
}

type Choice struct {
	Index   int      `json:"index"`
	Message *Message `json:"message"`
}

type ResponseBody struct {
	Choices []*Choice `json:"choices"` // 响应结果
}

func chatWithDeepseek(rb *RequestBody) {
	bs, err := sonic.Marshal(rb) // 转成json
	if err != nil {
		log.Printf("json序列化失败: %s", err)
		return
	}
	// 发送请求 bytes.NewReader(bs) 是请求体
	rq, _ := http.NewRequest(http.MethodPost, DeepseekUrl, bytes.NewReader(bs))
	// 添加请求头
	rq.Header.Add("Content-Type", "application/json")
	// 添加授权(鉴权)
	rq.Header.Add("Authorization", fmt.Sprintf("Bearer %s", config.APIKEY)) // 这里的key不做展示了
	client := http.Client{
		Timeout: 30 * time.Second, // 设置超时时间
	} // 创建http客户端
	resp, err := client.Do(rq) // 发送请求
	if err != nil {
		log.Printf("请求失败: %s", err)
		return
	}
	defer resp.Body.Close() // 关闭连接

	if resp.StatusCode != http.StatusOK {
		// 状态码不为200,则请求失败
		_, _ = io.Copy(os.Stdout, resp.Body) // 打印返回内容
		return
	}
	// 请求成功,读取返回内容
	bs, _ = io.ReadAll(resp.Body) //读取返回内容
	// fmt.Println(string(bs))

	var respBody ResponseBody
	err = json.Unmarshal(bs, &respBody)
	if err == nil {
		for k, v := range respBody.Choices {
			fmt.Println(k, v.Message.Content) // 打印内容
		}
	}else {
          fmt.Println(string(bs))
        }

}

func main() {
	rb := &RequestBody{
		Model: "deepseek-chat",
		Messages: []*Message{
			{
				Role:    "system",
				Content: "",
			},
			{
				Role:    "user",
				Content: "今天是2026年3月3号,离五一放假还有几天?",
			},
		},
		Stream: false, // 是否流式返回
	}

	chatWithDeepseek(rb)
}

image.png

把请求改为流式

  • 流式不处理的就是这样的 image.png
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"

	"agent/config"

	"github.com/bytedance/sonic"
)

const DeepseekUrl = "https://api.deepseek.com/chat/completions" // API地址

// 定义message结构体
type Message struct {
	Role    string `json:"role"`    // 角色"system", "user", "assistant"
	Content string `json:"content"` // 内容
}

// 定义请求体结构体
type RequestBody struct {
	Model    string     `json:"model"`    // 模型名称
	Messages []*Message `json:"messages"` // 消息列表
	Stream   bool       `json:"stream"`   // 是否流式返回
}

type Choice struct {
	Index   int      `json:"index"`
	Message *Message `json:"message"`
}

// 流式返回结果结构体
type StreamChoice struct {
	Index   int      `json:"index"`
	Message *Message `json:"delta"`
}

type ResponseBody struct {
	Choices []*Choice `json:"choices"` // 响应结果
}
type StreamResponseBody struct {
	Choices []*StreamChoice `json:"choices"` // 响应结果
}

func chatWithDeepseek(rb *RequestBody) {
	bs, err := sonic.Marshal(rb) // 转成json
	if err != nil {
		log.Printf("json序列化失败: %s", err)
		return
	}
	// 发送请求 bytes.NewReader(bs) 是请求体
	rq, _ := http.NewRequest(http.MethodPost, DeepseekUrl, bytes.NewReader(bs))
	// 添加请求头
	rq.Header.Add("Content-Type", "application/json")
	// 添加授权(鉴权)
	rq.Header.Add("Authorization", fmt.Sprintf("Bearer %s", config.APIKEY)) // 这里的key不做展示了
	client := http.Client{
		Timeout: 30 * time.Second, // 设置超时时间
	} // 创建http客户端
	resp, err := client.Do(rq) // 发送请求
	if err != nil {
		log.Printf("请求失败: %s", err)
		return
	}
	defer resp.Body.Close() // 关闭连接

	if resp.StatusCode != http.StatusOK {
		// 状态码不为200,则请求失败
		_, _ = io.Copy(os.Stdout, resp.Body) // 打印返回内容
		return
	}
	// 非流式返回
	// 请求成功,读取返回内容
	// bs, _ = io.ReadAll(resp.Body) //读取返回内容
	// fmt.Println(string(bs))

	// var respBody ResponseBody
	// err = json.Unmarshal(bs, &respBody)
	// if err == nil {
	// 	for k, v := range respBody.Choices {
	// 		fmt.Println(k, v.Message.Content) // 打印内容
	// 	}
	// }
	// 读取流式数据
	buffer := make([]byte, 1024*2) // 设置缓冲区大小2k
	for {
		n, err := resp.Body.Read(buffer)
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Printf("读取数据失败: %s", err)
			return
		}
		// fmt.Println(string(buffer[:n]))

		for _, segment := range bytes.Split(buffer[:n], []byte("data: ")) {
			// 去掉空行
			segment = bytes.TrimSpace(segment)
			if len(segment) == 0 {
				continue
			}
			// [DONE] 说明流式数据结束 一定要处理
			if string(segment) == "[DONE]" {
				break
			}

			// 进行json反序列化
			var streamResponse StreamResponseBody
			err := json.Unmarshal(segment, &streamResponse)
			if err == nil {
				fmt.Print(streamResponse.Choices[0].Message.Content) // 打印内容
			} else {
				log.Printf("json反序列化失败: %s", err)
				break
			}
		}
	}

}

func main() {
	rb := &RequestBody{
		Model: "deepseek-chat",
		Messages: []*Message{
			{
				Role:    "system",
				Content: "",
			},
			{
				Role:    "user",
				Content: "今天是2026年3月3号,离五一放假还有几天?",
			},
		},
		// Stream: false, // 否流式返回
		Stream: true, // 流式返回
	}

	chatWithDeepseek(rb)
}
  • 结果如下 image.png