DeepSeek大模型实现Tools/Functions调用的完整Go代码实现

一、Tools与Functions的核心概念

在AI大模型应用中,ToolsFunctions是扩展模型能力的关键机制:

  1. Tools(工具)
  • 外部API或服务的抽象封装
  • 示例:天气API、IP查询服务、日历服务
  • 特点:独立于模型存在,通过API调用实现特定功能
  1. Functions(函数)
  • 预定义的逻辑处理单元
  • 示例:日期处理、参数解析、数据格式化
  • 特点:直接与模型集成,决定何时调用特定工具
  1. 协同工作机制
用户输入 → 模型识别意图 → 选择Function → 调用对应Tool → 返回结果

二、系统架构设计

整体流程图

get_date
get_ip
get_weather
用户请求
HTTP Server
AI 模型
识别Function
系统时间
IP API
天气API
E/F/G
格式化响应
返回用户

三、Go语言完整实现

1. 核心代码实现

package main

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

// 环境变量配置(实际部署时应通过环境变量设置)
const (
	DeepSeekAPIKey  = "YOUR_DEEPSEEK_API_KEY"  // 替换为实际API密钥
	WeatherAPIKey   = "YOUR_WEATHER_API_KEY"   // 替换为OpenWeather API密钥
	DeepSeekAPIURL  = "https://api.deepseek.com/v1/chat/completions"
	WeatherAPIURL   = "https://api.openweathermap.org/data/2.5/weather"
)

// 定义支持的Functions
const (
	FuncGetDate    = "get_current_date"
	FuncGetIP      = "get_client_ip"
	FuncGetWeather = "get_weather_info"
)

// DeepSeek API请求结构
type DeepSeekRequest struct {
	Model    string         `json:"model"`
	Messages []Message      `json:"messages"`
	Tools    []Tool         `json:"tools,omitempty"`
}

// DeepSeek API响应结构
type DeepSeekResponse struct {
	Choices []struct {
		Message struct {
			ToolCalls []ToolCall `json:"tool_calls"`
		} `json:"message"`
	} `json:"choices"`
}

// 工具定义结构
type Tool struct {
	Type     string   `json:"type"`
	Function Function `json:"function"`
}

type Function struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Parameters any    `json:"parameters"`
}

type ToolCall struct {
	ID       string `json:"id"`
	Type     string `json:"type"`
	Function struct {
		Name      string `json:"name"`
		Arguments string `json:"arguments"`
	} `json:"function"`
}

// 定义工具参数结构
type WeatherParams struct {
	City string `json:"city"`
}

// HTTP请求处理结构
type APIRequest struct {
	Prompt string `json:"prompt"`
}

type APIResponse struct {
	Function string `json:"function"`
	Result   any    `json:"result"`
}

// 初始化工具定义
var availableTools = []Tool{
	{
		Type: "function",
		Function: Function{
			Name:        FuncGetWeather,
			Description: "获取指定城市的天气信息",
			Parameters: WeatherParams{},
		},
	},
	{
		Type: "function",
		Function: Function{
			Name:        FuncGetDate,
			Description: "获取当前系统日期和时间",
		},
	},
	{
		Type: "function",
		Function: Function{
			Name:        FuncGetIP,
			Description: "获取客户端IP地址",
		},
	},
}

// 调用DeepSeek模型
func callDeepSeek(prompt string) (*DeepSeekResponse, error) {
	requestBody := DeepSeekRequest{
		Model: "deepseek-chat",
		Messages: []Message{
			{
				Role:    "user",
				Content: prompt,
			},
		},
		Tools: availableTools,
	}

	jsonBody, _ := json.Marshal(requestBody)
	req, _ := http.NewRequest("POST", DeepSeekAPIURL, bytes.NewBuffer(jsonBody))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+DeepSeekAPIKey)

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("API请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	var response DeepSeekResponse
	if err := json.Unmarshal(body, &response); err != nil {
		return nil, fmt.Errorf("响应解析失败: %v", err)
	}

	return &response, nil
}

// 工具函数实现
func getCurrentDate() string {
	return time.Now().Format("2006-01-02 15:04:05 MST")
}

func getClientIP(r *http.Request) string {
	forwarded := r.Header.Get("X-Forwarded-For")
	if forwarded != "" {
		return strings.Split(forwarded, ",")[0]
	}
	return r.RemoteAddr
}

func getWeather(city string) (map[string]any, error) {
	url := fmt.Sprintf("%s?q=%s&appid=%s&units=metric&lang=zh_cn", 
		WeatherAPIURL, city, WeatherAPIKey)
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var result map[string]any
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	return map[string]any{
		"city":    city,
		"temp":    result["main"].(map[string]any)["temp"],
		"weather": result["weather"].([]any)[0].(map[string]any)["description"],
	}, nil
}

// HTTP处理函数
func handler(w http.ResponseWriter, r *http.Request) {
	var req APIRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		sendError(w, "无效的请求格式", http.StatusBadRequest)
		return
	}

	// 调用DeepSeek模型
	resp, err := callDeepSeek(req.Prompt)
	if err != nil {
		sendError(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// 处理工具调用
	if len(resp.Choices) == 0 || len(resp.Choices[0].Message.ToolCalls) == 0 {
		sendError(w, "未识别到有效操作", http.StatusBadRequest)
		return
	}

	toolCall := resp.Choices[0].Message.ToolCalls[0]
	var result any
	var errMsg string

	switch toolCall.Function.Name {
	case FuncGetDate:
		result = getCurrentDate()
	case FuncGetIP:
		result = getClientIP(r)
	case FuncGetWeather:
		var params WeatherParams
		if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &params); err != nil {
			errMsg = "天气参数解析失败"
			break
		}
		if weather, err := getWeather(params.City); err == nil {
			result = weather
		} else {
			errMsg = "获取天气信息失败"
		}
	default:
		errMsg = "不支持的功能调用"
	}

	if errMsg != "" {
		sendError(w, errMsg, http.StatusInternalServerError)
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(APIResponse{
		Function: toolCall.Function.Name,
		Result:   result,
	})
}

func sendError(w http.ResponseWriter, message string, code int) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(code)
	json.NewEncoder(w).Encode(map[string]string{"error": message})
}

func main() {
	http.HandleFunc("/query", handler)
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	fmt.Printf("Server running on :%s\n", port)
	http.ListenAndServe(":"+port, nil)
}

代码解析与使用说明

  1. 环境准备
# 设置环境变量(实际部署时推荐使用.env文件)
export DEEPSEEK_API_KEY="your_api_key_here"
export WEATHER_API_KEY="your_weather_key"
  1. 核心实现逻辑
  • 工具定义:通过availableTools声明系统支持的三个功能
  • 模型交互callDeepSeek方法实现与DeepSeek API的交互
  • 函数路由:根据返回的tool_call名称执行对应操作
  • 天气查询:集成OpenWeatherMap API实现真实数据获取
  1. 请求示例
curl -X POST http://localhost:8080/query \
  -H "Content-Type: application/json" \
  -d '{"prompt":"上海现在的气温是多少?"}'
  1. 响应结构
{
  "function": "get_weather_info",
  "result": {
    "city": "Shanghai",
    "temp": 28.5,
    "weather": "多云"
  }
}

关键点说明

  1. 深度集成DeepSeek
  • 使用官方API端点api.deepseek.com
  • 支持最新的deepseek-chat模型
  • 实现完整的工具调用(Tool Calls)流程
  1. 结构化参数处理
// 参数自动解析示例
var params WeatherParams
json.Unmarshal([]byte(toolCall.Function.Arguments), &params)
  1. 生产级特性
  • 环境变量配置管理
  • 完善的错误处理机制
  • 符合RESTful规范的API设计
  • 支持代理头部识别(X-Forwarded-For)
  1. 天气服务增强
  • 使用OpenWeatherMap官方API
  • 返回结构化天气数据
  • 支持多语言(中文)显示

本文由 www.dblens.com 知识分享,🚀 dblens for MySQL - 免费的AI大模型深度融合的一款MySQL可视化GUI数据库管理工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值