Skip to main content

LangChain Go Agents 完整教程

📋 目录

  1. 简介
  2. 环境设置
  3. 核心概念
  4. 实战示例
  5. 高级功能
  6. 最佳实践
  7. 常见问题

🌟 简介

LangChain Go 的 Agents(代理)是一个强大的框架,允许语言模型使用工具来解决复杂问题。代理可以:

  • 决定使用哪些工具
  • 根据工具结果调整策略
  • 维护对话记忆
  • 处理复杂的多步骤任务

主要特性

  • 智能决策: 代理可以根据输入智能选择合适的工具
  • 工具集成: 支持搜索、计算、API调用等各种工具
  • 记忆管理: 维护对话历史和上下文
  • 可扩展性: 轻松添加自定义工具和功能

⚙️ 环境设置

1. 安装依赖

go mod init langchain-agents-tutorial
go get github.com/tmc/langchaingo@latest

2. 环境变量设置

# 必需
export OPENAI_API_KEY="your-openai-api-key"

# 可选(用于搜索功能)
export SERPAPI_API_KEY="your-serpapi-key"

3. 项目结构

langchain-agents-tutorial/
├── main.go # 主程序
├── go.mod # Go模块文件
├── README.md # 文档
├── examples/ # 示例代码
├── tools/ # 自定义工具
└── docs/ # 详细文档

🎯 核心概念

1. Agent(代理)

代理是LangChain的核心组件,负责:

  • 理解用户输入
  • 决定使用哪些工具
  • 执行工具调用
  • 整合结果并响应

2. Tools(工具)

工具是代理可以使用的功能模块:

  • 搜索工具: 获取实时信息
  • 计算工具: 执行数学运算
  • API工具: 调用外部服务
  • 自定义工具: 特定业务逻辑

3. Memory(记忆)

记忆系统帮助代理:

  • 记住对话历史
  • 维护上下文信息
  • 总结长对话
  • 存储重要信息

4. Executor(执行器)

执行器负责:

  • 管理代理的执行流程
  • 处理错误和异常
  • 控制执行循环
  • 返回最终结果

🚀 实战示例

示例1: 基础代理

最简单的代理实现,无工具:

// 创建LLM
llm, err := openai.New(
openai.WithModel("gpt-3.5-turbo"),
openai.WithTemperature(0.7),
)

// 创建代理
agent := agents.NewOneShotAgent(
llm,
nil, // 无工具
agents.WithAgentType(agents.ZeroShotReactDescription),
)

// 创建执行器
executor := agents.NewExecutor(agent)

// 执行查询
result, err := chains.Run(ctx, executor, "什么是人工智能?")

特点:

  • 简单直接
  • 适合基础问答
  • 无外部依赖

示例2: 工具代理

使用搜索工具的代理:

// 创建搜索工具
searchTool := serpapi.New(os.Getenv("SERPAPI_API_KEY"))

// 创建代理
agent := agents.NewOneShotAgent(
llm,
[]tools.Tool{searchTool},
agents.WithAgentType(agents.ZeroShotReactDescription),
)

// 执行查询
result, err := chains.Run(ctx, executor, "2024年最新的AI技术趋势是什么?")

特点:

  • 可获取实时信息
  • 适合需要最新数据的查询
  • 支持复杂搜索

示例3: 对话代理

具有记忆功能的代理:

// 创建对话记忆
memory := memory.NewConversationBuffer()

// 创建对话代理
agent := agents.NewConversationalAgent(
llm,
nil,
agents.WithMemory(memory),
)

// 多轮对话
conversations := []string{
"我的名字是张三",
"我的名字是什么?",
}

特点:

  • 记住对话历史
  • 上下文连贯
  • 适合长对话

示例4: 自定义工具

创建专用工具:

type CalculatorTool struct{}

func (t *CalculatorTool) Name() string {
return "calculator"
}

func (t *CalculatorTool) Description() string {
return "用于执行数学计算的工具"
}

func (t *CalculatorTool) Call(ctx context.Context, input string) (string, error) {
// 实现计算逻辑
return result, nil
}

特点:

  • 高度定制化
  • 满足特定需求
  • 易于扩展

🔧 高级功能

1. 记忆管理

基础记忆

// 简单的对话缓冲
memory := memory.NewConversationBuffer()

摘要记忆

// 带摘要功能的记忆
summarizeMemory := memory.NewConversationSummaryBuffer(
llm,
memory.WithMaxTokenLimit(1000),
)

窗口记忆

// 固定窗口大小的记忆
windowMemory := memory.NewConversationBufferWindow(
memory.WithK(5), // 保留最后5轮对话
)

2. 工具组合

多工具代理

tools := []tools.Tool{
searchTool,
calculatorTool,
weatherTool,
databaseTool,
}

agent := agents.NewOneShotAgent(llm, tools, options...)

工具选择策略

// 精确匹配策略
agent := agents.NewOneShotAgent(
llm,
tools,
agents.WithAgentType(agents.ZeroShotReactDescription),
)

// 对话式策略
agent := agents.NewConversationalAgent(
llm,
tools,
agents.WithAgentType(agents.ConversationalReactDescription),
)

3. 错误处理

工具错误处理

func (t *CustomTool) Call(ctx context.Context, input string) (string, error) {
defer func() {
if r := recover(); r != nil {
log.Printf("工具执行panic: %v", r)
}
}()

// 验证输入
if input == "" {
return "", fmt.Errorf("输入不能为空")
}

// 执行逻辑
result, err := t.execute(input)
if err != nil {
return "", fmt.Errorf("执行失败: %w", err)
}

return result, nil
}

代理错误处理

executor := agents.NewExecutor(
agent,
agents.WithMaxIterations(10),
agents.WithErrorHandler(func(err error) error {
log.Printf("代理执行错误: %v", err)
return err
}),
)

4. 性能优化

并发执行

// 创建带缓存的LLM
llm, err := openai.New(
openai.WithModel("gpt-3.5-turbo"),
openai.WithMaxRetries(3),
openai.WithRequestTimeout(30*time.Second),
)

缓存机制

// 实现工具结果缓存
type CachedTool struct {
baseTool tools.Tool
cache map[string]string
mutex sync.RWMutex
}

func (t *CachedTool) Call(ctx context.Context, input string) (string, error) {
t.mutex.RLock()
if result, exists := t.cache[input]; exists {
t.mutex.RUnlock()
return result, nil
}
t.mutex.RUnlock()

result, err := t.baseTool.Call(ctx, input)
if err == nil {
t.mutex.Lock()
t.cache[input] = result
t.mutex.Unlock()
}

return result, err
}

✅ 最佳实践

1. 代理设计原则

单一职责

  • 每个工具专注单一功能
  • 避免工具功能重叠
  • 保持接口简洁

错误处理

  • 优雅处理工具失败
  • 提供有意义的错误信息
  • 实现重试机制

性能考虑

  • 使用适当的缓存
  • 控制API调用频率
  • 监控执行时间

2. 工具开发指南

工具接口实现

type Tool interface {
Name() string
Description() string
Call(ctx context.Context, input string) (string, error)
}

描述编写

func (t *WeatherTool) Description() string {
return `用于查询天气信息的工具。
输入格式:城市名称(如:北京、上海)
输出格式:包含温度、湿度、风速等信息的天气报告
示例:输入"北京",输出"北京今天晴天,温度22°C"`
}

输入验证

func (t *CalculatorTool) Call(ctx context.Context, input string) (string, error) {
// 输入清理
input = strings.TrimSpace(input)
if input == "" {
return "", fmt.Errorf("计算表达式不能为空")
}

// 输入验证
if !t.isValidExpression(input) {
return "", fmt.Errorf("无效的数学表达式: %s", input)
}

// 执行计算
return t.calculate(input)
}

3. 记忆策略

选择合适的记忆类型

// 短对话 - 使用简单缓冲
if conversationLength < 10 {
memory = memory.NewConversationBuffer()
}

// 长对话 - 使用摘要记忆
if conversationLength > 50 {
memory = memory.NewConversationSummaryBuffer(llm)
}

// 中等长度 - 使用窗口记忆
memory = memory.NewConversationBufferWindow(
memory.WithK(10),
)

记忆内容过滤

// 自定义记忆过滤器
type FilteredMemory struct {
baseMemory memory.ChatHistory
filter func(message schema.ChatMessage) bool
}

func (m *FilteredMemory) AddMessage(message schema.ChatMessage) error {
if m.filter(message) {
return m.baseMemory.AddMessage(message)
}
return nil
}

4. 监控和调试

日志记录

// 添加详细日志
executor := agents.NewExecutor(
agent,
agents.WithCallbacksManager(
callbacks.NewManager(
callbacks.WithVerbose(true),
),
),
)

性能监控

// 执行时间监控
start := time.Now()
result, err := chains.Run(ctx, executor, query)
duration := time.Since(start)

log.Printf("查询执行时间: %v", duration)
if duration > 30*time.Second {
log.Printf("慢查询警告: %s", query)
}

❓ 常见问题

Q1: 代理执行太慢怎么办?

A: 考虑以下优化策略:

  • 使用更快的模型(如gpt-3.5-turbo而非gpt-4)
  • 减少工具数量
  • 实现结果缓存
  • 设置超时限制

Q2: 工具调用失败怎么处理?

A: 实现健壮的错误处理:

func (t *MyTool) Call(ctx context.Context, input string) (string, error) {
// 重试机制
for attempt := 0; attempt < 3; attempt++ {
result, err := t.tryCall(ctx, input)
if err == nil {
return result, nil
}

if attempt < 2 {
time.Sleep(time.Duration(attempt+1) * time.Second)
}
}

return "工具暂时不可用,请稍后重试", nil
}

Q3: 如何控制代理的行为?

A: 通过提示工程和配置参数:

agent := agents.NewOneShotAgent(
llm,
tools,
agents.WithAgentType(agents.ZeroShotReactDescription),
agents.WithPrefix("你是一个专业的AI助手..."),
agents.WithSuffix("请始终提供准确和有用的信息"),
)

Q4: 记忆占用太多内存怎么办?

A: 使用记忆管理策略:

// 限制记忆大小
memory := memory.NewConversationSummaryBuffer(
llm,
memory.WithMaxTokenLimit(2000),
memory.WithReturnMessages(true),
)

// 定期清理记忆
if memorySize > threshold {
memory.Clear()
}

Q5: 如何调试代理的思考过程?

A: 启用详细日志和回调:

callbacks := callbacks.NewManager(
callbacks.WithVerbose(true),
callbacks.WithCallbacks([]callbacks.Handler{
&DebugHandler{},
}),
)

executor := agents.NewExecutor(
agent,
agents.WithCallbacksManager(callbacks),
)

📈 进阶主题

1. 自定义代理类型

创建专门的代理实现:

type CustomAgent struct {
llm llms.Model
tools []tools.Tool
memory memory.ChatHistory
}

func (a *CustomAgent) Plan(
ctx context.Context,
intermediate []schema.AgentStep,
inputs map[string]any,
) ([]schema.AgentAction, *schema.AgentFinish, error) {
// 自定义规划逻辑
return actions, nil, nil
}

2. 工具链组合

创建复合工具:

type ToolChain struct {
tools []tools.Tool
}

func (tc *ToolChain) Call(ctx context.Context, input string) (string, error) {
result := input
for _, tool := range tc.tools {
var err error
result, err = tool.Call(ctx, result)
if err != nil {
return "", err
}
}
return result, nil
}

3. 多模态代理

支持图像和文本:

type MultimodalTool struct{}

func (t *MultimodalTool) Call(ctx context.Context, input string) (string, error) {
// 检测输入类型
if t.isImageURL(input) {
return t.processImage(ctx, input)
}
return t.processText(ctx, input)
}

🎓 总结

LangChain Go Agents 提供了强大而灵活的框架来构建智能代理系统。通过合理使用工具、记忆和执行策略,可以创建能够处理复杂任务的AI应用。

核心要点

  1. 选择合适的代理类型:根据需求选择OneShot或Conversational
  2. 设计高质量工具:清晰的描述、健壮的实现、合适的错误处理
  3. 管理记忆策略:根据对话长度选择合适的记忆类型
  4. 优化性能:使用缓存、监控执行时间、处理错误
  5. 持续改进:监控代理行为、收集反馈、迭代优化

通过掌握这些概念和技术,您可以构建出强大、可靠、高效的AI代理系统。