第06篇-AgentForge-v0.1-基础对话引擎整合
·
【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 架构总览
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 知识表
| 篇号 | 核心主题 | 关键技能 | 毕业能力 |
|---|---|---|---|
| 01 | Agent 全景认知 | 理解 Agent 四组件与成熟度模型 | — |
| 02 | 开发环境搭建 | Provider 抽象层 + 流式输出 + Session | — |
| 03 | LLM 核心机制 | Prompt 结构化 + Token 管理 + Context Window | — |
| 04 | Function Calling | 工具定义 + 调用回路 + 并行执行 | — |
| 05 | 结构化输出 | Struct↔Schema + 校验重试 | — |
| 06 | v0.1 整合 | 完整 CLI 对话引擎 | ✅ 能搭建 Go Agent 环境并实现工具调用 |
六、AgentForge 版本演进路线
| 版本 | 新增核心能力 | 对应模块 | 篇号 |
|---|---|---|---|
| v0.1 ✅ | 基础对话 + Function Calling | 模块 1 | 01-06 |
| v0.2 | ReAct + 工具注册框架 + 短期记忆 | 模块 2 | 07-12 |
| v0.3 | Plan-and-Execute + DAG + ToT | 模块 3 | 13-17 |
| v0.4 | 多 Agent 协作引擎 | 模块 4 | 18-24 |
| v0.5 | 三层记忆 + RAG 知识库 | 模块 5 | 25-29 |
| v0.6 | MCP Server/Client 集成 | 模块 6 | 30-33 |
| v0.7 | Super Agent 核心 | 模块 7 | 34-38 |
| v1.0 | 生产部署 + 可观测性 | 模块 8 | 39-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 升级为自主推理引擎。
如果本篇内容对你有帮助,欢迎点赞收藏!有任何疑问,欢迎在评论区交流。
更多推荐


所有评论(0)