在《Tool 与 MCP 设计思路》一节中我们提到了几个工具,那么这一节我们就来手把手的写2个工具,并交给大模型使用。
核心代码目录: SuperBizAgent/internal/ai/tools
当前时间查询工具
那么就可以直接按照eino框架的规范,组装接口:
-
第一个参数是
toolName,用于表示工具名 -
第二个参数是
toolDesc,用于告诉大模型这个工具的功能 -
第三个参数是一个函数,里面写核心逻辑即可
// NewGetCurrentTimeTool 创建获取当前时间的工具
func NewGetCurrentTimeTool() tool.InvokableTool {
t, err := utils.InferOptionableTool(
"get_current_time",
"Get current system time in multiple formats. Returns the current time in seconds (Unix timestamp), milliseconds, and microseconds. Use this tool when you need to retrieve current system time for logging, timing operations, or timestamping events.",
func(ctx context.Context, input *GetCurrentTimeInput, opts ...tool.Option) (output string, err error) {
// 获取当前时间
now := time.Now()
// 计算各种时间格式
seconds := now.Unix() // 秒
milliseconds := now.UnixMilli() // 毫秒
microseconds := now.UnixMicro() // 微秒
timestamp := now.Format("2006-01-02 15:04:05.000000") // 可读格式
// 构建输出
timeOutput := GetCurrentTimeOutput{
Success: true,
Seconds: seconds,
Milliseconds: milliseconds,
Microseconds: microseconds,
Timestamp: timestamp,
Message: "Current time retrieved successfully",
}
// 转换为JSON
jsonBytes, err := json.MarshalIndent(timeOutput, "", " ")
if err != nil {
log.Printf("Error marshaling result to JSON: %v", err)
return "", err
}
return string(jsonBytes), nil
})
if err != nil {
log.Fatal(err)
}
return t
}函数的入参和出参,都可以用jsonschema的description来描述参数含义 。如此一来,我们的工具和工具描述就写好了
// GetCurrentTimeInput 获取当前时间的输入参数(无需输入)
type GetCurrentTimeInput struct {
// 无需输入参数
}
// GetCurrentTimeOutput 获取当前时间的输出结果
type GetCurrentTimeOutput struct {
Success bool `json:"success" jsonschema:"description=Indicates whether the time retrieval was successful"`
Seconds int64 `json:"seconds" jsonschema:"description=Current Unix timestamp in seconds since epoch (1970-01-01 00:00:00 UTC)"`
Milliseconds int64 `json:"milliseconds" jsonschema:"description=Current Unix timestamp in milliseconds since epoch (1970-01-01 00:00:00 UTC)"`
Microseconds int64 `json:"microseconds" jsonschema:"description=Current Unix timestamp in microseconds since epoch (1970-01-01 00:00:00 UTC)"`
Timestamp string `json:"timestamp" jsonschema:"description=Human-readable timestamp in format 'YYYY-MM-DD HH:MM:SS.microseconds'"`
Message string `json:"message" jsonschema:"description=Status message describing the operation result"`
}腾讯云日志MCP工具
通过 MCP Server 查询日志服务 CLS 中存储的日志数据,以实现大模型平台/工具与日志数据的结合。例如使用自然语言查询日志,降低日志查询复杂度 https://cloud.tencent.com/developer/mcp/server/11710
MCP配置: 【飞书文档】环境准备教程
首先我们创建一个 SSE MCP 客户端。创建后进行初始化,最后调用GetTools获取所有可用的工具即可
import (
"context"
e_mcp "github.com/cloudwego/eino-ext/components/tool/mcp"
"github.com/cloudwego/eino/components/tool"
"github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/mcp"
)
func GetLogMcpTool() ([]tool.BaseTool, error) {
ctx := context.Background()
// 1. 创建客户端
cli, err := client.NewSSEMCPClient("https://mcp-api.tencent-cloud.com/sse/ac4XXXXXX")
if err != nil {
return []tool.BaseTool{}, err
}
err = cli.Start(ctx)
if err != nil {
return []tool.BaseTool{}, err
}
// 2. 协商协议
initRequest := mcp.InitializeRequest{}
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
initRequest.Params.ClientInfo = mcp.Implementation{
Name: "example-client",
Version: "1.0.0",
}
if _, err = cli.Initialize(ctx, initRequest); err != nil {
return []tool.BaseTool{}, err
}
// 3. 获取工具
mcpTools, err := e_mcp.GetTools(ctx, &e_mcp.Config{Cli: cli})
if err != nil {
return []tool.BaseTool{}, err
}
return mcpTools, nil
}代码实战:让大模型拥有使用工具的能力
核心代码: SuperBizAgent/internal/ai/cmd/llm_tool_cmd/main.go
下面的ApiKey记得改成你的,才能运行起来。
-
第一步创建一个大模型
openai.NewChatModel -
第二步创建可用的工具,将工具绑定到大模型上
chatModel.BindTools
- 第三步创建一个处理链,运行
package main
import (
tools2 "SuperBizAgent/internal/ai/tools"
"context"
"fmt"
"github.com/cloudwego/eino-ext/components/model/openai"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/schema"
)
func main() {
ctx := context.Background()
// 创建 ChatModel
config := &openai.ChatModelConfig{
APIKey: "xxx",
Model: "deepseek-v3-1-terminus",
BaseURL: "https://ark.cn-beijing.volces.com/api/v3",
}
chatModel, err := openai.NewChatModel(ctx, config)
if err != nil {
panic(err)
}
// 获取工具信息, 用于绑定到 ChatModel
toolList, _ := tools2.GetLogMcpTool()
toolList = append(toolList, tools2.NewGetCurrentTimeTool())
toolInfos := make([]*schema.ToolInfo, 0)
var info *schema.ToolInfo
for _, todoTool := range toolList {
info, err = todoTool.Info(ctx)
if err != nil {
panic(err)
}
toolInfos = append(toolInfos, info)
}
// 将 tools 绑定到 ChatModel
err = chatModel.BindTools(toolInfos)
if err != nil {
panic(err)
}
// 创建一个完整的处理链
chain := compose.NewChain[[]*schema.Message, *schema.Message]()
chain.AppendChatModel(chatModel, compose.WithNodeName("chat_model"))
// 编译并运行 chain
agent, err := chain.Compile(ctx)
if err != nil {
panic(err)
}
// 运行示例
resp, err := agent.Invoke(ctx, []*schema.Message{
{
Role: schema.User,
Content: "告诉我你有哪些工具可以使用",
},
})
if err != nil {
panic(err)
}
// 输出结果
fmt.Println(resp.Content)
}(base) ➜ llm_tool_cmd git:(main) ✗ go run main.go
根据我的工具配置,我可以使用以下功能:
## 可用工具
### 1. **GetCurrentTimestamp** - 获取当前时间戳
- 功能:获取当前时间的毫秒级时间戳
- 参数:无
### 2. **GetRegionCodeByName** - 根据地区名称搜索地区代码
- 功能:通过地区名称(如"广州"或"Hong Kong")搜索对应的地区参数代码
- 必需参数:`searchText`(地区名称)
- 可选参数:`language`(搜索语言,默认中文)
### 3. **GetTopicInfoByName** - 根据主题名称搜索主题信息
- 功能:通过主题名称搜索日志主题信息
- 必需参数:`region`(地区代码)
- 可选参数:`searchText`(主题名称)、`preciseSearch`(精确搜索)
### 4. **SearchLog** - 搜索日志
- 功能:根据查询参数搜索和分析日志
- 必需参数:`From`(开始时间)、`To`(结束时间)、`Query`(查询语句)、`Region`(地区)
- 可选参数:`TopicId`、`Limit`、`Sort`、`Offset`等
### 5. **TextToSearchLogQuery** - 自然语言转日志查询
- 功能:将用户的自然语言描述转换为日志查询语句
- 必需参数:`Region`(地区)、`Text`(用户输入的自然语言)
- 可选参数:`TopicId`(主题ID)
### 6. **get_current_time** - 获取当前系统时间
- 功能:获取当前系统时间(秒、毫秒、微秒级时间戳)
- 参数:无
这些工具主要用于日志搜索、地区信息查询和时间相关操作。如果您需要执行特定任务,请告诉我您的具体需求,我可以使用相应的工具来帮助您。