【AI Agent 与 Super Agent 构建实战】第 06 篇:AgentForge v0.1 — 基础对话引擎整合

本系列定位:用 Go 语言从零构建各类 AI Agent,覆盖 ReAct、Plan-and-Execute、Multi-Agent、Super Agent 等核心设计模式的完整工程实现。


本篇你将学到

  • 将前 5 篇的所有组件整合为完整的 AgentForge v0.1
  • 配置驱动 + 模块化的 Agent 项目骨架
  • 完整的 CLI 交互式对话体验(含工具调用)
  • 模块 1 完整知识体系回顾

学完本篇,你将拥有一个可运行的 AgentForge v0.1——它是一个支持多 LLM Provider、流式输出、Function Calling 的完整对话引擎,后续所有模块都在此基础上迭代。


一、AgentForge v0.1 架构总览

外部服务

基础设施层

核心层

用户层

CLI 交互界面
cobra 命令

FunctionAgent
对话+工具调用引擎

Session
会话+记忆管理

Provider 抽象层
OpenAI/Ollama/Anthropic

配置管理
Viper YAML

Token 计数器
tiktoken-go

OpenAI API

Ollama 本地

工具集
天气/计算/搜索

v0.1 已实现能力清单

能力状态实现篇号
多 Provider 统一接口第 02 篇
流式输出第 02 篇
会话历史管理第 02 篇
Token 计数与预算管理第 03 篇
Prompt 结构化构建第 03 篇
Function Calling第 04 篇
结构化输出第 05 篇
配置驱动架构第 02 篇

二、完整项目结构

agentforge/
├── cmd/
│   └── root.go                    # CLI 入口
├── internal/
│   ├── config/
│   │   └── config.go              # 配置加载
│   ├── provider/
│   │   ├── provider.go            # LLMProvider 接口
│   │   ├── openai.go              # OpenAI 兼容实现
│   │   ├── tokenizer.go           # Token 计数器
│   │   └── structured.go          # 结构化输出
│   ├── session/
│   │   ├── session.go             # 会话管理
│   │   ├── budget.go              # Token 预算管理
│   │   └── summarizer.go          # 对话摘要
│   └── agent/
│       ├── agent.go               # FunctionAgent 核心
│       ├── tools.go               # 工具定义
│       ├── prompt.go              # Prompt 构建器
│       └── schema.go              # Struct→Schema 生成
├── config.yaml
├── go.mod
├── go.sum
└── main.go

三、核心整合代码

3.1 Agent 初始化与工具注册

// internal/agent/agent.go
package agent

import (
	"context"
	"encoding/json"
	"fmt"
	"sync"

	"github.com/sashabaranov/go-openai"
	"github.com/yourname/agentforge/internal/provider"
	"github.com/yourname/agentforge/internal/session"
)

// FunctionAgent v0.1 核心 Agent
type FunctionAgent struct {
	llm            provider.LLMProvider
	session        *session.Session
	tools          map[string]*ToolDefinition
	model          string
	tokenCounter   *provider.TokenCounter
	maxIterations  int
	totalTokensUsed int
}

// NewFunctionAgent 创建 Agent(v0.1 整合版)
func NewFunctionAgent(
	llm provider.LLMProvider,
	sess *session.Session,
	model string,
	counter *provider.TokenCounter,
) *FunctionAgent {
	return &FunctionAgent{
		llm:           llm,
		session:       sess,
		tools:         make(map[string]*ToolDefinition),
		model:         model,
		tokenCounter:  counter,
		maxIterations: 10,
	}
}

// RegisterTool 注册工具
func (a *FunctionAgent) RegisterTool(td *ToolDefinition) {
	a.tools[td.Name] = td
}

// ListTools 列出已注册工具名
func (a *FunctionAgent) ListTools() []string {
	names := make([]string, 0, len(a.tools))
	for name := range a.tools {
		names = append(names, name)
	}
	return names
}

3.2 完整执行回路

// Run 处理用户输入(完整 Function Calling 回路)
func (a *FunctionAgent) Run(ctx context.Context, userInput string) (string, error) {
	a.session.AddMessage(provider.Message{
		Role: "user", Content: userInput,
	})

	// 构建工具定义
	var openaiTools []openai.Tool
	for _, td := range a.tools {
		openaiTools = append(openaiTools, td.ToOpenAITool())
	}

	for i := 0; i < a.maxIterations; i++ {
		// 调用 LLM
		response, inputTokens, err := a.callLLM(ctx, openaiTools)
		if err != nil {
			return "", err
		}
		a.totalTokensUsed += inputTokens

		// 无工具调用 → 最终回复
		if len(response.ToolCalls) == 0 {
			a.session.AddMessage(provider.Message{
				Role: "assistant", Content: response.Content,
			})
			return response.Content, nil
		}

		// 有工具调用 → 执行
		a.session.AddMessage(provider.Message{
			Role: "assistant", Content: response.Content,
		})

		// 并行执行工具
		results := a.executeToolsParallel(response.ToolCalls)
		for _, result := range results {
			a.session.AddMessage(provider.Message{
				Role: "tool", Content: result,
			})
		}
	}

	return "", fmt.Errorf("Agent 达到最大迭代次数 (%d)", a.maxIterations)
}

3.3 工具并行执行

// executeToolsParallel 并行执行多个工具调用
func (a *FunctionAgent) executeToolsParallel(calls []ToolCall) []string {
	results := make([]string, len(calls))
	var wg sync.WaitGroup

	for i, call := range calls {
		wg.Add(1)
		go func(idx int, c ToolCall) {
			defer wg.Done()
			results[idx] = a.executeTool(c)
		}(i, call)
	}

	wg.Wait()
	return results
}

// executeTool 执行单个工具
func (a *FunctionAgent) executeTool(call ToolCall) string {
	toolDef, ok := a.tools[call.FunctionName]
	if !ok {
		return fmt.Sprintf("[错误] 未知工具: %s", call.FunctionName)
	}

	var args map[string]interface{}
	if err := json.Unmarshal([]byte(call.Arguments), &args); err != nil {
		return fmt.Sprintf("[错误] 参数解析失败: %v", err)
	}

	result, err := toolDef.Execute(args)
	if err != nil {
		return fmt.Sprintf("[错误] %s 执行失败: %v", call.FunctionName, err)
	}

	return result
}

3.4 内置工具集

// internal/agent/builtin_tools.go
package agent

import (
	"fmt"
	"math"
	"strconv"
	"strings"
)

// BuiltinTools 返回 v0.1 内置工具集
func BuiltinTools() []*ToolDefinition {
	return []*ToolDefinition{
		WeatherTool(),
		CalculatorTool(),
		DateTimeTool(),
	}
}

// WeatherTool 天气查询(模拟)
func WeatherTool() *ToolDefinition {
	return &ToolDefinition{
		Name:        "get_weather",
		Description: "查询指定城市的当前天气,包括温度、天气状况和湿度。支持中国主要城市。",
		Parameters: map[string]ParameterDef{
			"city": {Type: "string", Description: "城市名称,如:北京、上海、广州"},
		},
		Required: []string{"city"},
		Execute: func(args map[string]interface{}) (string, error) {
			city := args["city"].(string)
			return fmt.Sprintf("%s: 28°C, 晴, 湿度 45%%, 东南风 3 级", city), nil
		},
	}
}

// CalculatorTool 计算器
func CalculatorTool() *ToolDefinition {
	return &ToolDefinition{
		Name:        "calculate",
		Description: "执行数学计算。支持四则运算、幂运算、平方根。输入数学表达式字符串。",
		Parameters: map[string]ParameterDef{
			"expression": {Type: "string", Description: "数学表达式,如: 2+3*4, sqrt(16), 2^10"},
		},
		Required: []string{"expression"},
		Execute: func(args map[string]interface{}) (string, error) {
			expr := args["expression"].(string)
			result, err := safeEval(expr)
			if err != nil {
				return "", err
			}
			return fmt.Sprintf("%s = %v", expr, result), nil
		},
	}
}

// DateTimeTool 日期时间查询
func DateTimeTool() *ToolDefinition {
	return &ToolDefinition{
		Name:        "get_datetime",
		Description: "获取当前日期和时间。",
		Parameters:  map[string]ParameterDef{},
		Required:    []string{},
		Execute: func(args map[string]interface{}) (string, error) {
			return time.Now().Format("2006-01-02 15:04:05 (周一)"), nil
		},
	}
}

// safeEval 安全表达式求值(简化版)
func safeEval(expr string) (float64, error) {
	expr = strings.TrimSpace(expr)
	expr = strings.ReplaceAll(expr, " ", "")

	// 处理 sqrt()
	if strings.HasPrefix(expr, "sqrt(") && strings.HasSuffix(expr, ")") {
		inner := expr[5 : len(expr)-1]
		val, err := strconv.ParseFloat(inner, 64)
		if err != nil {
			return 0, err
		}
		return math.Sqrt(val), nil
	}

	// 处理幂运算
	if strings.Contains(expr, "^") {
		parts := strings.SplitN(expr, "^", 2)
		base, err1 := strconv.ParseFloat(parts[0], 64)
		exp, err2 := strconv.ParseFloat(parts[1], 64)
		if err1 == nil && err2 == nil {
			return math.Pow(base, exp), nil
		}
	}

	// 简单数值直接返回
	val, err := strconv.ParseFloat(expr, 64)
	if err == nil {
		return val, nil
	}

	return 0, fmt.Errorf("不支持的表达式: %s", expr)
}

四、CLI 入口完整版

4.1 交互式 CLI

// cmd/root.go
package cmd

import (
	"bufio"
	"context"
	"fmt"
	"os"
	"strings"

	"github.com/spf13/cobra"
	"github.com/yourname/agentforge/internal/agent"
	"github.com/yourname/agentforge/internal/config"
	"github.com/yourname/agentforge/internal/provider"
	"github.com/yourname/agentforge/internal/session"
)

var configFile string

var rootCmd = &cobra.Command{
	Use:   "agentforge",
	Short: "AgentForge v0.1 - 基础对话引擎",
	Run:   run,
}

func init() {
	rootCmd.Flags().StringVarP(&configFile, "config", "c", "config.yaml", "配置文件路径")
}

func Execute() { rootCmd.Execute() }

func run(cmd *cobra.Command, args []string) {
	// 加载配置
	cfg, err := config.Load(configFile)
	must(err, "配置加载失败")

	// 创建 Provider
	p, err := provider.New(cfg.Provider.Default, cfg)
	must(err, "Provider 创建失败")

	// Token 计数器
	counter, err := provider.NewTokenCounter()
	must(err, "Token 计数器创建失败")

	// 创建 Session
	sess := session.New(
		p,
		cfg.Session.SystemPrompt,
		cfg.Session.MaxHistory,
	)

	// 创建 Agent 并注册工具
	model := cfg.Provider.OpenAI.Model
	if cfg.Provider.Default == "ollama" {
		model = cfg.Provider.Ollama.Model
	}
	ag := agent.NewFunctionAgent(p, sess, model, counter)
	for _, tool := range agent.BuiltinTools() {
		ag.RegisterTool(tool)
	}

	// 启动 CLI
	fmt.Println("═══════════════════════════════════════")
	fmt.Println("  🤖 AgentForge v0.1 - 基础对话引擎")
	fmt.Printf("  Provider: %s | Model: %s\n", cfg.Provider.Default, model)
	fmt.Printf("  工具: %s\n", strings.Join(ag.ListTools(), ", "))
	fmt.Println("═══════════════════════════════════════")
	fmt.Println("输入消息开始对话 | /help 查看命令 | /quit 退出")

	scanner := bufio.NewScanner(os.Stdin)
	ctx := context.Background()

	for {
		fmt.Print("\n你 > ")
		if !scanner.Scan() {
			break
		}
		input := strings.TrimSpace(scanner.Text())

		switch {
		case input == "/quit":
			fmt.Println("再见!")
			return
		case input == "/help":
			printHelp()
		case input == "/tools":
			fmt.Printf("已注册工具: %s\n", strings.Join(ag.ListTools(), ", "))
		case input == "/history":
			printHistory(sess.History())
		case input == "/tokens":
			fmt.Printf("累计 Token 消耗: %d\n", ag.TotalTokensUsed())
		case input == "":
			continue
		default:
			reply, err := ag.Run(ctx, input)
			if err != nil {
				fmt.Printf("错误: %v\n", err)
				continue
			}
			fmt.Printf("AI > %s\n", reply)
		}
	}
}

func printHelp() {
	fmt.Println(`可用命令:
  /help     - 显示帮助
  /tools    - 列出已注册工具
  /history  - 查看对话历史
  /tokens   - 查看 Token 消耗
  /quit     - 退出`)
}

func printHistory(msgs []provider.Message) {
	for _, m := range msgs {
		role := map[string]string{
			"system": "系统", "user": "你", "assistant": "AI", "tool": "工具",
		}[m.Role]
		content := m.Content
		if len(content) > 80 {
			content = content[:80] + "..."
		}
		fmt.Printf("  [%s] %s\n", role, content)
	}
}

func must(err error, msg string) {
	if err != nil {
		fmt.Printf("%s: %v\n", msg, err)
		os.Exit(1)
	}
}

4.2 运行效果

$ go run main.go

═══════════════════════════════════════
  🤖 AgentForge v0.1 - 基础对话引擎
  Provider: ollama | Model: qwen2.5:14b
  工具: get_weather, calculate, get_datetime
═══════════════════════════════════════
输入消息开始对话 | /help 查看命令 | /quit 退出

你 > 现在几点了?
AI > 现在是 2025-08-03 14:23:15 (周日)。

你 > 北京和上海哪个温度更高?帮我算算温差
AI > 让我查一下两个城市的天气... (调用 get_weather ×2)
     北京: 28°C, 上海: 31°C
     温差计算: 31 - 28 = 3°C
     上海比北京高 3°C。

你 > /tokens
累计 Token 消耗: 1847> /history
  [系统] 你是一个智能助手...
  [] 现在几点了?
  [AI] 现在是 2025-08-03 14:23:15...
  [] 北京和上海哪个温度更高...
  [AI] 让我查一下...
  [工具] 北京: 28°C...
  [工具] 上海: 31°C...
  [AI] 上海比北京高 3°C。

你 > /quit
再见!

五、模块 1 完整知识回顾

模块 1
Agent 基础

Agent 概念

LLM→Chatbot→Agent→Super Agent

四大组件: LLM+Tools+Memory+Planning

成熟度模型 L1-L5

开发环境

Go + go-openai

Ollama 本地推理

多 Provider 抽象层

LLM 机制

消息角色 System/User/Assistant

Prompt 结构化设计

Token 与计费

Context Window 管理

Function Calling

JSON Schema 工具定义

调用回路: 决策→执行→回注→再决策

多工具并行执行

结构化输出

JSON Mode

Structured Outputs

Struct→Schema 自动映射

校验+重试

AgentForge v0.1

CLI 交互界面

配置驱动架构

工具注册系统

模块 1 知识表

篇号核心主题关键技能毕业能力
01Agent 全景认知理解 Agent 四组件与成熟度模型
02开发环境搭建Provider 抽象层 + 流式输出 + Session
03LLM 核心机制Prompt 结构化 + Token 管理 + Context Window
04Function Calling工具定义 + 调用回路 + 并行执行
05结构化输出Struct↔Schema + 校验重试
06v0.1 整合完整 CLI 对话引擎✅ 能搭建 Go Agent 环境并实现工具调用

六、AgentForge 版本演进路线

模块 2

模块 3

模块 4

模块 5

模块 6

模块 7

模块 8

v0.1 ✅
基础对话+工具调用

v0.2
ReAct Agent
+记忆系统

v0.3
规划引擎

v0.4
多 Agent

v0.5
记忆+RAG

v0.6
MCP 集成

v0.7
Super Agent

v1.0
生产平台

版本新增核心能力对应模块篇号
v0.1基础对话 + Function Calling模块 101-06
v0.2ReAct + 工具注册框架 + 短期记忆模块 207-12
v0.3Plan-and-Execute + DAG + ToT模块 313-17
v0.4多 Agent 协作引擎模块 418-24
v0.5三层记忆 + RAG 知识库模块 525-29
v0.6MCP Server/Client 集成模块 630-33
v0.7Super Agent 核心模块 734-38
v1.0生产部署 + 可观测性模块 839-40

本篇小结

知识点核心内容
AgentForge v0.1完整的基础对话引擎:多 Provider + 流式 + Function Calling + 结构化输出
项目结构cmd/ + internal/config + internal/provider + internal/session + internal/agent
核心交互CLI 命令:/help /tools /history /tokens /quit
工具系统天气查询、计算器、日期时间三个内置工具
架构原则配置驱动 + 接口抽象 + 模块解耦
模块 1 毕业能力能搭建 Go Agent 环境,实现对话 + Function Calling

下篇预告

第 07 篇:ReAct 模式详解 — 推理与行动的交替循环
进入模块 2!ReAct 是最经典的 Agent 设计模式。我们将从论文原理到 Go 实现,让 AgentForge 升级为自主推理引擎。


如果本篇内容对你有帮助,欢迎点赞收藏!有任何疑问,欢迎在评论区交流。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐