AutoGen Agent 概念篇

一、Agent 的三种类型(本质区别)

🤖 1. OpenAIChatAgent —— "大脑"

本质:LLM 调用器

用户消息 → OpenAIChatAgent → 调用 API → LLM 返回 → 格式化输出

核心原理

  • 内部封装了 ChatClient(兼容 OpenAI 协议)
  • 负责把消息转成 API 能懂的格式
  • 拿到 LLM 响应后,再转成 AutoGen 的消息格式

关键点

  • 必须配置 systemMessage(人设)
  • 必须调用 .RegisterMessageConnector()(格式转换)
  • 本身没有记忆,每次调用都是独立的

适用场景:需要 LLM 能力的任何地方

👤 2. UserProxyAgent —— "传话筒"

本质:人机交互接口

核心原理

  • 不调用 LLM
  • 根据 HumanInputMode 决定是否等待用户输入
  • 把用户输入转成 AutoGen 消息格式

三种模式详解

ALWAYS 每轮必等用户 收到消息 → 等待输入 → 转发给用户 → 继续
NEVER 完全自动 收到消息 → 返回默认回复 → 继续
TERMINATE 条件触发 收到消息 → 检查终止条件 → 满足则等待,否则自动

关键点

  • 用于人在回路(Human-in-the-loop)场景
  • 可以随时介入控制对话走向
  • 适合需要人工审核/决策的场景

适用场景:代码审查、内容审核、关键决策

🎯 3. AssistantAgent —— "简化版大脑"

本质:OpenAIChatAgent 的快捷封装

核心原理

  • 内部还是调用 LLM
  • 预设了默认配置(systemMessage、工具注册等)
  • 代码更简洁,但灵活性降低

对比

OpenAIChatAgent:需要手动配置 chatClient、systemMessage
AssistantAgent: 一行代码搞定,但配置项少

适用场景:快速原型、简单任务


二、消息格式(AutoGen 的通用语言)

📨 消息的本质

AutoGen 里所有消息都实现 IMessage 接口,核心字段:


┌─────────────────────────────────────┐
│ IMessage                            │
├─────────────────────────────────────┤
│ Role: User / Assistant / System     │
│ Content: 消息内容(文本/图片等)     │
│ From: 发送者 Agent 名称              │
│ Metadata: 额外数据(时间戳、类型等) │
└─────────────────────────────────────┘

📦 常见消息类型

类型用途示例
TextMessage 纯文本 "你好"
ImageMessage 图片 图片 URL
ToolCallMessage 工具调用 "调用 GetWeather"
ToolCallResultMessage 工具返回结果 "晴天,25 度"
MultiModalMessage 多模态 文本 + 图片

🔄 消息流转原理

用户输入
   ↓
[UserProxyAgent] → 转成 TextMessage(Role.User)
   ↓
[GroupChat] → 添加到消息列表
   ↓
[OpenAIChatAgent] → 读取历史消息 → 调用 LLM
   ↓
LLM 返回
   ↓
[OpenAIChatAgent] → 转成 TextMessage(Role.Assistant)
   ↓
[PrintMessage] → 控制台输出
   ↓
消息列表追加

关键点

  • 所有 Agent 之间只通过消息通信
  • 消息列表是对话的唯一状态
  • 每次对话 = 读取历史 → 生成新消息 → 追加

三、中间件(Middleware)—— Agent 的"插件系统"

🧩 中间件是什么?

本质:AOP(面向切面编程)

请求 → 中间件 1 → 中间件 2 → Agent 核心 → 中间件 2 → 中间件 1 → 响应
       ↓           ↓                      ↓           ↓           ↓
     日志       认证                    调用 LLM    后处理     格式化

🔧 三个核心中间件原理

1. .RegisterMessageConnector()

作用:格式转换器

原理

  • AutoGen 内部消息格式 ↔ LLM API 格式
  • 没有它,Agent 无法理解消息

必须注册:所有调用 LLM 的 Agent 都必须有


2. .RegisterPrintMessage()

作用:调试输出

原理

  • 拦截消息
  • 格式化打印到控制台
  • 原样返回消息(不影响流程)

可选:生产环境建议去掉(减少 IO)


3. .RegisterMiddleware()

作用:自定义逻辑

原理

RegisterMiddleware(async (msgs, agent, reply, ct) =>
{
    // ① 前置处理(收到消息后,调用 Agent 前)
    Console.WriteLine($"收到 {msgs.Count} 条消息");
    
    // ② 调用下一个中间件或 Agent 核心
    var response = await reply(agent, msgs, ct);
    
    // ③ 后置处理(拿到响应后,返回前)
    Console.WriteLine($"响应完成");
    
    return response; // 必须返回
})

📊 中间件执行顺序

注册顺序:A → B → C

执行流程:
请求 → A(前置) → B(前置) → C(前置) → Agent → C(后置) → B(后置) → A(后置) → 响应

洋葱模型:先注册的最外层,最后注册的最内层

四、消息历史记录(对话的"记忆")

🧠 为什么需要历史记录?

问题:LLM 是无状态的,每次调用都是新的

解决:手动维护消息列表

轮次 1: 用户:"你好" → Agent:"你好!"
轮次 2: 用户:"我是谁" → Agent:❌ 不知道(没有历史)

解决方案:
轮次 2: 把轮次 1 的消息一起发给 LLM → Agent:"你是 XXX"

📝 实现原理

// ① 创建历史列表
var history = new List<IMessage>();

// ② 每轮对话后追加
history.Add(userMessage);
history.Add(agentResponse);

// ③ 下一轮对话时传入历史
await agent.GenerateReplyAsync(history, options, ct);

⚠️ 关键注意事项

问题原理解决方案
上下文超限 LLM 有 token 上限(如 128K) 定期摘要压缩历史
性能下降 消息越多,调用越慢 只保留最近 N 条
无关信息 早期消息可能不相关 按主题筛选历史

五、核心架构图

┌─────────────────────────────────────────────────────────┐
│                    AutoGen 架构                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ┌──────────────┐    ┌──────────────┐    ┌───────────┐ │
│  │ OpenAIChat   │    │ UserProxy    │    │ Assistant │ │
│  │   Agent      │    │   Agent      │    │   Agent   │ │
│  └──────┬───────┘    └──────┬───────┘    └─────┬─────┘ │
│         │                   │                   │       │
│         └───────────────────┼───────────────────┘       │
│                             │                           │
│                  ┌──────────▼──────────┐                │
│                  │   Middleware Stack  │                │
│                  │  (消息转换器 + 日志)  │                │
│                  └──────────┬──────────┘                │
│                             │                           │
│                  ┌──────────▼──────────┐                │
│                  │   Message History   │                │
│                  │   (List<IMessage>)  │                │
│                  └─────────────────────┘                │
│                                                         │
└─────────────────────────────────────────────────────────┘

六、总结(一句话理解)

概念一句话本质
OpenAIChatAgent LLM 调用器,负责和模型对话
UserProxyAgent 人机接口,负责等待用户输入
AssistantAgent 简化版 OpenAIChatAgent
消息格式 Agent 之间的通用语言
中间件 消息处理管道,前后置逻辑
历史记录 对话状态的唯一载体

 

原理讲完了!核心就三点

  1. Agent 是消息处理器(输入消息 → 处理 → 输出消息)
  2. 中间件是处理管道(可以插入自定义逻辑)
  3. 历史是对话状态(没有历史,LLM 就没有记忆)
posted @ 2026-08-18 09:44  天才卧龙  阅读(5)  评论(0)    收藏  举报