LangChain Go Agents 完整教程
📋 目录
🌟 简介
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应用。
核心要点
- 选择合适的代理类型:根据需求选择OneShot或Conversational
- 设计高质量工具:清晰的描述、健壮的实现、合适的错误处理
- 管理记忆策略:根据对话长度选择合适的记忆类型
- 优化性能:使用缓存、监控执行时间、处理错误
- 持续改进:监控代理行为、收集反馈、迭代优化
通过掌握这些概念和技术,您可以构建出强大、可靠、高效的AI代理系统。