소스 검색

add chapter6 && fix tiny mistakes

jjyaoao 9 달 전
부모
커밋
4a62545c41

+ 4 - 6
README.md

@@ -38,7 +38,7 @@
 | <strong>第二部分:构建你的大语言模型智能体</strong> |  |  |
 | [第四章 智能体经典范式构建](./docs/chapter4/第四章%20智能体经典范式构建.md) | 手把手实现 ReAct、Plan-and-Solve、Reflection | ✅ |
 | [第五章 基于低代码平台的智能体搭建](./docs/chapter5/第五章%20基于低代码平台的智能体搭建.md) | 了解Coze、n8n等商业化低代码智能体平台使用 | 🚧 |
-| [第六章 框架开发实践](./docs/chapter6/第六章%20框架开发实践.md) | AutoGen、AgentScope、LangGraph 等主流框架应用 | 🚧 |
+| [第六章 框架开发实践](./docs/chapter6/第六章%20框架开发实践.md) | AutoGen、AgentScope、LangGraph 等主流框架应用 |  |
 | [第七章 构建你的Agent框架](./docs/chapter7/第七章%20构建你的Agent框架.md) | 从0开始构建智能体框架 | 🚧 |
 | <strong>第三部分:高级知识扩展</strong> |  |  |
 | [第八章 推理与规划](./docs/chapter8/第八章%20推理与规划.md) | CoT, 逻辑推理, 搜索与规划 | 🚧 |
@@ -55,15 +55,13 @@
 
 ### 社区贡献精选 (Community Blog)
 
-&emsp;&emsp;欢迎大家将在学习 Hello-Agents 或 Agent 相关技术中的独到见解、实践总结,以 PR 的形式贡献到社区精选。如果是独立于正文的内容,也可以投稿至Extra-Chapter!如果是独立于正文的内容,也可以投稿至Extra-Chapter!
-
-<strong>暂无内容,期待你的第一次贡献!</strong>
+&emsp;&emsp;欢迎大家将在学习 Hello-Agents 或 Agent 相关技术中的独到见解、实践总结,以 PR 的形式贡献到社区精选。如果是独立于正文的内容,也可以投稿至Extra-Chapter!<strong>期待你的第一次贡献!</strong>
 
 ### PDF 版本下载
 
 &emsp;&emsp;*<strong>本 Hello-Agents PDF 教程完全开源免费。为防止各类营销号加水印后贩卖给多智能体系统初学者,我们特地在 PDF 文件中预先添加了不影响阅读的 Datawhale 开源标志水印,敬请谅解~</strong>*
 
-> *Hello-Agents PDF : https://github.com/datawhalechina/Hello-Agents/releases/tag/PDF*  
+> *Hello-Agents PDF : https://github.com/datawhalechina/Hello-Agents/releases/tag/PDF(尚未完成)*  
 > *Hello-Agents PDF 国内下载地址 : https://www.datawhale.cn/learn/summary/XXX* 
 
 ## 💡 如何学习
@@ -118,7 +116,7 @@
 ## Star History
 
 <div align='center'>
-    <img src="./docs/images/star-history-2025913.png" alt="Datawhale" width="90%">
+    <img src="./docs/images/star-history-2025916.png" alt="Datawhale" width="90%">
 </div>
 
 <div align="center">

+ 217 - 0
code/chapter6/AgentScopeDemo/README.md

@@ -0,0 +1,217 @@
+# AgentScope 三国狼人杀案例
+
+本目录包含第六章 AgentScope 框架的完整实战案例,展示了如何使用 AgentScope 构建一个融合中国古典文化元素的多智能体在线游戏。
+
+## 📁 文件说明
+
+- `main_cn.py` - 主要游戏逻辑和控制器
+- `prompt_cn.py` - 中文提示词管理
+- `game_roles.py` - 游戏角色定义和配置
+- `structured_output_cn.py` - 结构化输出模型定义
+- `utils_cn.py` - 游戏工具函数和辅助方法
+- `README.md` - 本说明文档
+
+## 🎮 案例特点
+
+- **消息驱动架构**:展示 AgentScope 的核心消息传递机制
+- **并发协作**:演示多智能体同时在线的实时交互
+- **角色扮演**:每个智能体具备双重身份(游戏角色+三国人物)
+- **结构化输出**:通过 Pydantic 模型约束智能体行为
+- **容错机制**:单个智能体异常不影响整体游戏流程
+
+## 🛠️ 环境准备
+
+### 1. 安装依赖
+
+```bash
+pip install agentscope
+pip install dashscope
+pip install pydantic
+```
+
+### 2. 配置环境变量
+
+设置阿里云 DashScope API Key:
+
+```bash
+# Linux/Mac
+export DASHSCOPE_API_KEY="your-api-key-here"
+
+# Windows PowerShell
+$env:DASHSCOPE_API_KEY="your-api-key-here"
+
+# Windows CMD
+set DASHSCOPE_API_KEY=your-api-key-here
+```
+
+获取 API Key:https://dashscope.console.aliyun.com/apiKey
+
+### 3. 运行游戏
+
+```bash
+python main_cn.py
+```
+
+## 🎭 游戏角色说明
+
+### 游戏角色
+- **狼人**:夜晚击杀好人,白天隐藏身份
+- **预言家**:每晚查验一名玩家身份
+- **女巫**:拥有解药和毒药各一瓶
+- **猎人**:被投票出局时可开枪带走一名玩家
+- **村民**:通过推理和投票找出狼人
+
+### 三国人物
+- **刘备**:仁德宽厚,善于团结众人
+- **关羽**:忠义刚烈,言辞直接
+- **张飞**:性格豪爽,容易冲动
+- **诸葛亮**:智慧超群,分析透彻
+- **曹操**:雄才大略,善于权谋
+- **司马懿**:深谋远虑,城府极深
+
+## 🏗️ 架构设计
+
+### 分层架构
+```
+游戏控制层 (ThreeKingdomsWerewolfGame)
+    ├── 游戏状态管理
+    ├── 流程控制
+    └── 胜负判定
+
+智能体交互层 (MsgHub)
+    ├── 消息路由
+    ├── 并发处理
+    └── 状态同步
+
+角色建模层 (DialogAgent)
+    ├── 角色提示词
+    ├── 结构化输出
+    └── 行为约束
+```
+
+### 核心组件
+
+**1. 消息中心 (MsgHub)**
+```python
+async with MsgHub(
+    participants=self.werewolves,
+    enable_auto_broadcast=True
+) as hub:
+    # 狼人夜晚讨论
+    for wolf in self.werewolves:
+        await wolf(structured_model=DiscussionModelCN)
+```
+
+**2. 结构化输出**
+```python
+class VoteModelCN(BaseModel):
+    vote: str = Field(description="投票目标玩家姓名")
+    reason: str = Field(description="投票理由")
+    confidence: int = Field(ge=1, le=10, description="信心程度")
+```
+
+**3. 并发管道**
+```python
+vote_msgs = await fanout_pipeline(
+    self.alive_players,
+    msg=vote_announcement,
+    structured_model=get_vote_model_cn(self.alive_players),
+    enable_gather=False,
+)
+```
+
+## 🎯 游戏流程
+
+### 夜晚阶段
+1. **狼人讨论**:狼人通过 MsgHub 协商击杀目标
+2. **预言家查验**:预言家选择查验对象
+3. **女巫行动**:女巫决定是否使用解药/毒药
+
+### 白天阶段
+1. **死亡公布**:公布夜晚死亡玩家
+2. **自由讨论**:所有存活玩家参与讨论
+3. **投票淘汰**:投票选择淘汰对象
+4. **猎人技能**:被淘汰的猎人可开枪
+
+## 🔧 自定义配置
+
+### 修改游戏人数
+```python
+# 在 main_cn.py 中修改
+await game.setup_game(player_count=8)  # 支持 6-12 人
+```
+
+### 添加新角色
+```python
+# 在 game_roles.py 中添加
+ROLES["守护者"] = {
+    "description": "守护者",
+    "ability": "每晚可以守护一名玩家",
+    "team": "好人阵营"
+}
+```
+
+### 自定义提示词
+```python
+# 在 prompt_cn.py 中修改
+def get_role_prompt(role: str, character: str) -> str:
+    # 自定义角色提示词逻辑
+    pass
+```
+
+## 🐛 常见问题
+
+### Q: 游戏无法启动?
+A: 检查以下几点:
+- 确认 DASHSCOPE_API_KEY 环境变量已设置
+- 验证 API Key 是否有效
+- 检查网络连接是否正常
+
+### Q: 智能体输出格式错误?
+A: 可能原因:
+- 模型理解能力限制
+- 提示词设计不够清晰
+- 结构化输出约束过于复杂
+
+### Q: 游戏流程卡住?
+A: 建议:
+- 检查 MsgHub 的消息传递
+- 验证并发管道的执行状态
+- 查看控制台错误日志
+
+## 📚 技术亮点
+
+### 1. 消息驱动架构
+- 智能体间完全通过消息交互
+- 支持异步并发处理
+- 天然的分布式能力
+
+### 2. 结构化输出约束
+- 游戏规则转化为代码约束
+- 提升系统稳定性和可预测性
+- 便于调试和监控
+
+### 3. 双重角色建模
+- 游戏角色 + 三国人物的创新设计
+- 展现不同人格的策略差异
+- 增强游戏的趣味性和真实感
+
+## 🚀 扩展方向
+
+- **增加游戏模式**:支持更多狼人杀变体
+- **优化 AI 策略**:提升智能体的游戏水平
+- **可视化界面**:开发 Web 或桌面客户端
+- **实时观战**:支持人类玩家观战和互动
+- **数据分析**:统计游戏数据和智能体表现
+
+## 🤝 贡献指南
+
+欢迎提交 Issue 和 Pull Request:
+- 报告游戏 Bug 或异常
+- 提出新功能建议
+- 优化代码实现
+- 完善文档说明
+
+---
+
+*本案例是 Hello-Agents 教程第六章的核心实战项目,展示了 AgentScope 框架在构建复杂多智能体应用方面的强大能力。*

+ 114 - 0
code/chapter6/AgentScopeDemo/game_roles.py

@@ -0,0 +1,114 @@
+# -*- coding: utf-8 -*-
+"""三国狼人杀角色定义"""
+from typing import Dict, List
+
+
+class GameRoles:
+    """游戏角色管理类"""
+    
+    ROLES = {
+        "狼人": {
+            "description": "狼人",
+            "ability": "夜晚可以击杀一名玩家",
+            "win_condition": "消灭所有好人或与好人数量相等",
+            "team": "狼人阵营"
+        },
+        "预言家": {
+            "description": "预言家",
+            "ability": "每晚可以查验一名玩家的身份",
+            "win_condition": "消灭所有狼人",
+            "team": "好人阵营"
+        },
+        "女巫": {
+            "description": "女巫",
+            "ability": "拥有解药和毒药各一瓶,可以救人或杀人",
+            "win_condition": "消灭所有狼人",
+            "team": "好人阵营"
+        },
+        "猎人": {
+            "description": "猎人",
+            "ability": "被投票出局时可以开枪带走一名玩家",
+            "win_condition": "消灭所有狼人",
+            "team": "好人阵营"
+        },
+        "村民": {
+            "description": "村民",
+            "ability": "无特殊技能,依靠推理和投票",
+            "win_condition": "消灭所有狼人",
+            "team": "好人阵营"
+        },
+        "守护者": {
+            "description": "守护者",
+            "ability": "每晚可以守护一名玩家免受狼人攻击",
+            "win_condition": "消灭所有狼人",
+            "team": "好人阵营"
+        }
+    }
+    
+    CHARACTER_TRAITS = {
+        "刘备": "仁德宽厚,善于团结众人,说话温和有礼",
+        "关羽": "忠义刚烈,言辞直接,重情重义",
+        "张飞": "性格豪爽,说话大声直接,容易冲动",
+        "诸葛亮": "智慧超群,分析透彻,言辞谨慎",
+        "赵云": "忠勇双全,话语简洁有力",
+        "曹操": "雄才大略,善于权谋,话语犀利",
+        "司马懿": "深谋远虑,城府极深,言辞含蓄",
+        "周瑜": "才华横溢,略显傲气,分析精准",
+        "孙权": "年轻有为,善于决断,话语果决"
+    }
+    
+    @classmethod
+    def get_role_desc(cls, role: str) -> str:
+        """获取角色描述"""
+        return cls.ROLES.get(role, {}).get("description", "未知角色")
+    
+    @classmethod
+    def get_role_ability(cls, role: str) -> str:
+        """获取角色技能"""
+        return cls.ROLES.get(role, {}).get("ability", "无特殊技能")
+    
+    @classmethod
+    def get_character_trait(cls, character: str) -> str:
+        """获取角色性格特点"""
+        return cls.CHARACTER_TRAITS.get(character, "性格温和,说话得体")
+    
+    @classmethod
+    def is_werewolf(cls, role: str) -> bool:
+        """判断是否为狼人"""
+        return role == "狼人"
+    
+    @classmethod
+    def is_villager_team(cls, role: str) -> bool:
+        """判断是否为好人阵营"""
+        return cls.ROLES.get(role, {}).get("team") == "好人阵营"
+    
+    @classmethod
+    def get_standard_setup(cls, player_count: int) -> List[str]:
+        """获取标准角色配置"""
+        if player_count == 6:
+            return ["狼人", "狼人", "预言家", "女巫", "村民", "村民"]
+        elif player_count == 8:
+            return ["狼人", "狼人", "狼人", "预言家", "女巫", "猎人", "村民", "村民"]
+        elif player_count == 9:
+            return ["狼人", "狼人", "狼人", "预言家", "女巫", "猎人", "守护者", "村民", "村民"]
+        else:
+            # 默认配置:约1/3狼人
+            werewolf_count = max(1, player_count // 3)
+            roles = ["狼人"] * werewolf_count
+            
+            # 添加神职
+            remaining = player_count - werewolf_count
+            if remaining >= 1:
+                roles.append("预言家")
+                remaining -= 1
+            if remaining >= 1:
+                roles.append("女巫")
+                remaining -= 1
+            if remaining >= 1:
+                roles.append("猎人")
+                remaining -= 1
+            
+            # 剩余为村民
+            roles.extend(["村民"] * remaining)
+            
+            return roles

+ 347 - 0
code/chapter6/AgentScopeDemo/main_cn.py

@@ -0,0 +1,347 @@
+# -*- coding: utf-8 -*-
+"""
+三国狼人杀 - 基于AgentScope的中文版狼人杀游戏
+融合三国演义角色和传统狼人杀玩法
+"""
+import asyncio
+import os
+import random
+from typing import List, Dict, Optional
+
+from agentscope.agent import ReActAgent
+from agentscope.model import DashScopeChatModel
+from agentscope.pipeline import MsgHub, sequential_pipeline, fanout_pipeline
+from agentscope.formatter import DashScopeMultiAgentFormatter
+
+from prompt_cn import ChinesePrompts
+from game_roles import GameRoles
+from structured_output_cn import (
+    DiscussionModelCN,
+    get_vote_model_cn,
+    WitchActionModelCN,
+    get_seer_model_cn,
+    get_hunter_model_cn,
+    WerewolfKillModelCN
+)
+from utils_cn import (
+    check_winning_cn,
+    majority_vote_cn,
+    get_chinese_name,
+    format_player_list,
+    GameModerator,
+    MAX_GAME_ROUND,
+    MAX_DISCUSSION_ROUND,
+)
+
+
+class ThreeKingdomsWerewolfGame:
+    """三国狼人杀游戏主类"""
+    
+    def __init__(self):
+        self.players: Dict[str, ReActAgent] = {}
+        self.roles: Dict[str, str] = {}
+        self.moderator = GameModerator()
+        self.alive_players: List[ReActAgent] = []
+        self.werewolves: List[ReActAgent] = []
+        self.villagers: List[ReActAgent] = []
+        self.seer: List[ReActAgent] = []
+        self.witch: List[ReActAgent] = []
+        self.hunter: List[ReActAgent] = []
+        
+        # 女巫道具状态
+        self.witch_has_antidote = True
+        self.witch_has_poison = True
+        
+    async def create_player(self, role: str, character: str) -> ReActAgent:
+        """创建具有三国背景的玩家"""
+        name = get_chinese_name(character)
+        self.roles[name] = role
+        
+        agent = ReActAgent(
+            name=name,
+            sys_prompt=ChinesePrompts.get_role_prompt(role, character),
+            model=DashScopeChatModel(
+                model_name="qwen-max",
+                api_key=os.environ["DASHSCOPE_API_KEY"],
+                enable_thinking=True,
+            ),
+            formatter=DashScopeMultiAgentFormatter(),
+        )
+        
+        # 角色身份确认
+        await agent.observe(
+            await self.moderator.announce(
+                f"【{name}】你在这场三国狼人杀中扮演{GameRoles.get_role_desc(role)},"
+                f"你的角色是{character}。{GameRoles.get_role_ability(role)}"
+            )
+        )
+        
+        self.players[name] = agent
+        return agent
+    
+    async def setup_game(self, player_count: int = 6):
+        """设置游戏"""
+        print("🎮 开始设置三国狼人杀游戏...")
+        
+        # 获取角色配置
+        roles = GameRoles.get_standard_setup(player_count)
+        characters = random.sample([
+            "刘备", "关羽", "张飞", "诸葛亮", "赵云",
+            "曹操", "司马懿", "周瑜", "孙权"
+        ], player_count)
+        
+        # 创建玩家
+        for i, (role, character) in enumerate(zip(roles, characters)):
+            agent = await self.create_player(role, character)
+            self.alive_players.append(agent)
+            
+            # 分配到对应阵营
+            if role == "狼人":
+                self.werewolves.append(agent)
+            elif role == "预言家":
+                self.seer.append(agent)
+            elif role == "女巫":
+                self.witch.append(agent)
+            elif role == "猎人":
+                self.hunter.append(agent)
+            else:
+                self.villagers.append(agent)
+        
+        # 游戏开始公告
+        await self.moderator.announce(
+            f"三国狼人杀游戏开始!参与者:{format_player_list(self.alive_players)}"
+        )
+        
+        print(f"✅ 游戏设置完成,共{len(self.alive_players)}名玩家")
+    
+    async def werewolf_phase(self, round_num: int):
+        """狼人阶段"""
+        if not self.werewolves:
+            return None
+            
+        await self.moderator.announce(f"🐺 狼人请睁眼,选择今晚要击杀的目标...")
+        
+        # 狼人讨论
+        async with MsgHub(
+            self.werewolves,
+            enable_auto_broadcast=True,
+            announcement=await self.moderator.announce(
+                f"狼人们,请讨论今晚的击杀目标。存活玩家:{format_player_list(self.alive_players)}"
+            ),
+        ) as werewolves_hub:
+            # 讨论阶段
+            for _ in range(MAX_DISCUSSION_ROUND):
+                for wolf in self.werewolves:
+                    await wolf(structured_model=DiscussionModelCN)
+            
+            # 投票击杀
+            werewolves_hub.set_auto_broadcast(False)
+            kill_votes = await fanout_pipeline(
+                self.werewolves,
+                msg=await self.moderator.announce("请选择击杀目标"),
+                structured_model=WerewolfKillModelCN,
+                enable_gather=False,
+            )
+            
+            # 统计投票
+            votes = {}
+            for i, vote_msg in enumerate(kill_votes):
+                votes[self.werewolves[i].name] = vote_msg.metadata.get("target")
+            
+            killed_player, _ = majority_vote_cn(votes)
+            return killed_player
+    
+    async def seer_phase(self):
+        """预言家阶段"""
+        if not self.seer:
+            return
+            
+        seer_agent = self.seer[0]
+        await self.moderator.announce("🔮 预言家请睁眼,选择要查验的玩家...")
+        
+        check_result = await seer_agent(
+            structured_model=get_seer_model_cn(self.alive_players)
+        )
+        
+        target_name = check_result.metadata.get("target")
+        target_role = self.roles.get(target_name, "村民")
+        
+        # 告知预言家结果
+        result_msg = f"查验结果:{target_name}是{'狼人' if target_role == '狼人' else '好人'}"
+        await seer_agent.observe(await self.moderator.announce(result_msg))
+    
+    async def witch_phase(self, killed_player: str):
+        """女巫阶段"""
+        if not self.witch:
+            return killed_player, None
+            
+        witch_agent = self.witch[0]
+        await self.moderator.announce("🧙‍♀️ 女巫请睁眼...")
+        
+        # 告知女巫死亡信息
+        death_info = f"今晚{killed_player}被狼人击杀" if killed_player else "今晚平安无事"
+        await witch_agent.observe(await self.moderator.announce(death_info))
+        
+        # 女巫行动
+        witch_action = await witch_agent(structured_model=WitchActionModelCN)
+        
+        saved_player = None
+        poisoned_player = None
+        
+        if witch_action.metadata.get("use_antidote") and self.witch_has_antidote:
+            if killed_player:
+                saved_player = killed_player
+                self.witch_has_antidote = False
+                await witch_agent.observe(await self.moderator.announce(f"你使用解药救了{killed_player}"))
+        
+        if witch_action.metadata.get("use_poison") and self.witch_has_poison:
+            poisoned_player = witch_action.metadata.get("target_name")
+            if poisoned_player:
+                self.witch_has_poison = False
+                await witch_agent.observe(await self.moderator.announce(f"你使用毒药毒杀了{poisoned_player}"))
+        
+        # 确定最终死亡玩家
+        final_killed = killed_player if not saved_player else None
+        
+        return final_killed, poisoned_player
+    
+    async def hunter_phase(self, shot_by_hunter: str):
+        """猎人阶段"""
+        if not self.hunter:
+            return None
+            
+        hunter_agent = self.hunter[0]
+        if hunter_agent.name == shot_by_hunter:
+            await self.moderator.announce("🏹 猎人发动技能,可以带走一名玩家...")
+            
+            hunter_action = await hunter_agent(
+                structured_model=get_hunter_model_cn(self.alive_players)
+            )
+            
+            if hunter_action.metadata.get("shoot"):
+                target = hunter_action.metadata.get("target")
+                await self.moderator.announce(f"猎人{hunter_agent.name}开枪带走了{target}")
+                return target
+        
+        return None
+    
+    def update_alive_players(self, dead_players: List[str]):
+        """更新存活玩家列表"""
+        for dead_name in dead_players:
+            if dead_name:
+                # 从存活列表移除
+                self.alive_players = [p for p in self.alive_players if p.name != dead_name]
+                # 从各阵营移除
+                self.werewolves = [p for p in self.werewolves if p.name != dead_name]
+                self.villagers = [p for p in self.villagers if p.name != dead_name]
+                self.seer = [p for p in self.seer if p.name != dead_name]
+                self.witch = [p for p in self.witch if p.name != dead_name]
+                self.hunter = [p for p in self.hunter if p.name != dead_name]
+    
+    async def day_phase(self, round_num: int):
+        """白天阶段"""
+        await self.moderator.day_announcement(round_num)
+        
+        # 讨论阶段
+        async with MsgHub(
+            self.alive_players,
+            enable_auto_broadcast=True,
+            announcement=await self.moderator.announce(
+                f"现在开始自由讨论。存活玩家:{format_player_list(self.alive_players)}"
+            ),
+        ) as all_hub:
+            # 每人发言一轮
+            await sequential_pipeline(self.alive_players)
+            
+            # 投票阶段
+            all_hub.set_auto_broadcast(False)
+            vote_msgs = await fanout_pipeline(
+                self.alive_players,
+                await self.moderator.announce("请投票选择要淘汰的玩家"),
+                structured_model=get_vote_model_cn(self.alive_players),
+                enable_gather=False,
+            )
+            
+            # 统计投票
+            votes = {}
+            for i, vote_msg in enumerate(vote_msgs):
+                votes[self.alive_players[i].name] = vote_msg.metadata.get("vote")
+            
+            voted_out, vote_count = majority_vote_cn(votes)
+            await self.moderator.vote_result_announcement(voted_out, vote_count)
+            
+            return voted_out
+    
+    async def run_game(self):
+        """运行游戏主循环"""
+        try:
+            await self.setup_game()
+            
+            for round_num in range(1, MAX_GAME_ROUND + 1):
+                print(f"\n🌙 === 第{round_num}轮游戏开始 ===")
+                
+                # 夜晚阶段
+                await self.moderator.night_announcement(round_num)
+                
+                # 狼人击杀
+                killed_player = await self.werewolf_phase(round_num)
+                
+                # 预言家查验
+                await self.seer_phase()
+                
+                # 女巫行动
+                final_killed, poisoned_player = await self.witch_phase(killed_player)
+                
+                # 更新死亡玩家
+                night_deaths = [p for p in [final_killed, poisoned_player] if p]
+                self.update_alive_players(night_deaths)
+                
+                # 死亡公告
+                await self.moderator.death_announcement(night_deaths)
+                
+                # 检查胜利条件
+                winner = check_winning_cn(self.alive_players, self.roles)
+                if winner:
+                    await self.moderator.game_over_announcement(winner)
+                    return
+                
+                # 白天阶段
+                voted_out = await self.day_phase(round_num)
+                
+                # 猎人技能
+                hunter_shot = await self.hunter_phase(voted_out)
+                
+                # 更新死亡玩家
+                day_deaths = [p for p in [voted_out, hunter_shot] if p]
+                self.update_alive_players(day_deaths)
+                
+                # 检查胜利条件
+                winner = check_winning_cn(self.alive_players, self.roles)
+                if winner:
+                    await self.moderator.game_over_announcement(winner)
+                    return
+                
+                print(f"第{round_num}轮结束,存活玩家:{format_player_list(self.alive_players)}")
+        
+        except Exception as e:
+            print(f"❌ 游戏运行出错:{e}")
+            import traceback
+            traceback.print_exc()
+
+
+async def main():
+    """主函数"""
+    # 检查环境变量
+    if "DASHSCOPE_API_KEY" not in os.environ:
+        print("❌ 请设置环境变量 DASHSCOPE_API_KEY")
+        return
+    
+    print("🎮 欢迎来到三国狼人杀!")
+    
+    # 创建并运行游戏
+    game = ThreeKingdomsWerewolfGame()
+    await game.run_game()
+
+
+if __name__ == "__main__":
+    asyncio.run(main())

+ 56 - 0
code/chapter6/AgentScopeDemo/prompt_cn.py

@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+"""三国狼人杀中文提示词"""
+
+class ChinesePrompts:
+    """中文提示词管理类"""
+    
+    @staticmethod
+    def get_role_prompt(role: str, character: str) -> str:
+        """获取角色提示词"""
+        base_prompt = f"""你是{character},在这场三国狼人杀游戏中扮演{role}。
+
+请严格按照以下JSON格式回复,不要添加任何其他文字:
+{{
+    "reach_agreement": true/false,
+    "confidence_level": 1-10的数字,
+    "key_evidence": "你的证据或观点"
+}}
+
+角色特点:
+"""
+        
+        if role == "狼人":
+            return base_prompt + f"""
+- 你是狼人阵营,目标是消灭所有好人
+- 夜晚可以与其他狼人协商击杀目标
+- 白天要隐藏身份,误导好人
+- 以{character}的性格说话和行动
+"""
+        elif role == "预言家":
+            return base_prompt + f"""
+- 你是好人阵营的预言家,目标是找出所有狼人
+- 每晚可以查验一名玩家的真实身份
+- 要合理公布查验结果,引导好人投票
+- 以{character}的智慧和洞察力分析局势
+"""
+        elif role == "女巫":
+            return base_prompt + f"""
+- 你是好人阵营的女巫,拥有解药和毒药各一瓶
+- 解药可以救活被狼人击杀的玩家
+- 毒药可以毒杀一名玩家
+- 要谨慎使用道具,在关键时刻发挥作用
+"""
+        elif role == "猎人":
+            return base_prompt + f"""
+- 你是好人阵营的猎人
+- 被投票出局时可以开枪带走一名玩家
+- 要在关键时刻使用技能,带走狼人
+- 以{character}的勇猛和决断力行动
+"""
+        else:  # 村民
+            return base_prompt + f"""
+- 你是好人阵营的村民
+- 没有特殊技能,只能通过推理和投票
+- 要仔细观察,找出狼人的破绽
+- 以{character}的性格参与讨论
+"""

+ 1 - 0
code/chapter6/AgentScopeDemo/requirements.txt

@@ -0,0 +1 @@
+agentscope==1.0.2

+ 138 - 0
code/chapter6/AgentScopeDemo/structured_output_cn.py

@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+"""三国狼人杀游戏的结构化输出模型"""
+from typing import Literal, Optional, List
+from pydantic import BaseModel, Field
+from agentscope.agent import AgentBase
+
+
+class DiscussionModelCN(BaseModel):
+    """中文版讨论输出格式"""
+    
+    reach_agreement: bool = Field(
+        description="是否已达成一致意见",
+    )
+    confidence_level: int = Field(
+        description="对当前推理的信心程度(1-10)",
+        ge=1, le=10
+    )
+    key_evidence: Optional[str] = Field(
+        description="支持你观点的关键证据",
+        default=None
+    )
+
+
+def get_vote_model_cn(agents: list[AgentBase]) -> type[BaseModel]:
+    """获取中文版投票模型"""
+    
+    class VoteModelCN(BaseModel):
+        """中文版投票输出格式"""
+        
+        vote: Literal[tuple(_.name for _ in agents)] = Field(
+            description="你要投票淘汰的玩家姓名",
+        )
+        reason: str = Field(
+            description="投票理由,简要说明为什么选择此人",
+        )
+        suspicion_level: int = Field(
+            description="对被投票者的怀疑程度(1-10)",
+            ge=1, le=10
+        )
+    
+    return VoteModelCN
+
+
+class WitchActionModelCN(BaseModel):
+    """中文版女巫行动模型"""
+    
+    use_antidote: bool = Field(
+        description="是否使用解药救人",
+        default=False
+    )
+    use_poison: bool = Field(
+        description="是否使用毒药杀人", 
+        default=False
+    )
+    target_name: Optional[str] = Field(
+        description="目标玩家姓名(救人或毒杀的对象)",
+        default=None
+    )
+    action_reason: Optional[str] = Field(
+        description="行动理由",
+        default=None
+    )
+
+
+def get_seer_model_cn(agents: list[AgentBase]) -> type[BaseModel]:
+    """获取中文版预言家模型"""
+    
+    class SeerModelCN(BaseModel):
+        """中文版预言家查验格式"""
+        
+        target: Literal[tuple(_.name for _ in agents)] = Field(
+            description="要查验的玩家姓名",
+        )
+        check_reason: str = Field(
+            description="查验此人的原因",
+        )
+        priority_level: int = Field(
+            description="查验优先级(1-10)",
+            ge=1, le=10
+        )
+    
+    return SeerModelCN
+
+
+def get_hunter_model_cn(agents: list[AgentBase]) -> type[BaseModel]:
+    """获取中文版猎人模型"""
+    
+    class HunterModelCN(BaseModel):
+        """中文版猎人开枪格式"""
+        
+        shoot: bool = Field(
+            description="是否使用开枪技能",
+        )
+        target: Optional[Literal[tuple(_.name for _ in agents)]] = Field(
+            description="开枪目标玩家姓名",
+            default=None
+        )
+        shoot_reason: Optional[str] = Field(
+            description="开枪理由",
+            default=None
+        )
+    
+    return HunterModelCN
+
+
+class WerewolfKillModelCN(BaseModel):
+    """中文版狼人击杀模型"""
+    
+    target: str = Field(
+        description="要击杀的玩家姓名",
+    )
+    kill_strategy: str = Field(
+        description="击杀策略说明",
+    )
+    team_coordination: Optional[str] = Field(
+        description="与狼队友的配合计划",
+        default=None
+    )
+
+
+class GameAnalysisModelCN(BaseModel):
+    """中文版游戏分析模型"""
+    
+    suspected_werewolves: List[str] = Field(
+        description="怀疑的狼人名单",
+        default_factory=list
+    )
+    trusted_players: List[str] = Field(
+        description="信任的玩家名单", 
+        default_factory=list
+    )
+    key_clues: List[str] = Field(
+        description="关键线索列表",
+        default_factory=list
+    )
+    next_strategy: str = Field(
+        description="下一步策略",
+    )

+ 173 - 0
code/chapter6/AgentScopeDemo/utils_cn.py

@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+"""三国狼人杀游戏工具函数"""
+import asyncio
+import random
+from typing import List, Dict, Optional, Any
+from collections import Counter
+
+from agentscope.agent import AgentBase
+from agentscope.message import Msg
+
+# 游戏常量
+MAX_GAME_ROUND = 10
+MAX_DISCUSSION_ROUND = 3
+CHINESE_NAMES = [
+    "刘备", "关羽", "张飞", "诸葛亮", "赵云",
+    "曹操", "司马懿", "典韦", "许褚", "夏侯惇", 
+    "孙权", "周瑜", "陆逊", "甘宁", "太史慈",
+    "吕布", "貂蝉", "董卓", "袁绍", "袁术"
+]
+
+
+def get_chinese_name(character: str = None) -> str:
+    """获取中文角色名"""
+    if character and character in CHINESE_NAMES:
+        return character
+    return random.choice(CHINESE_NAMES)
+
+
+def format_player_list(players: List[AgentBase], show_roles: bool = False) -> str:
+    """格式化玩家列表为中文显示"""
+    if not players:
+        return "无玩家"
+    
+    if show_roles:
+        return "、".join([f"{p.name}({getattr(p, 'role', '未知')})" for p in players])
+    else:
+        return "、".join([p.name for p in players])
+
+
+def majority_vote_cn(votes: Dict[str, str]) -> tuple[str, int]:
+    """中文版多数投票统计"""
+    if not votes:
+        return "无人", 0
+    
+    vote_counts = Counter(votes.values())
+    most_voted = vote_counts.most_common(1)[0]
+    
+    return most_voted[0], most_voted[1]
+
+
+def check_winning_cn(alive_players: List[AgentBase], roles: Dict[str, str]) -> Optional[str]:
+    """检查中文版游戏胜利条件"""
+    alive_roles = [roles.get(p.name, "村民") for p in alive_players]
+    werewolf_count = alive_roles.count("狼人")
+    villager_count = len(alive_roles) - werewolf_count
+    
+    if werewolf_count == 0:
+        return "好人阵营胜利!所有狼人已被淘汰!"
+    elif werewolf_count >= villager_count:
+        return "狼人阵营胜利!狼人数量已达到或超过好人!"
+    
+    return None
+
+
+def analyze_speech_pattern(speech: str) -> Dict[str, Any]:
+    """分析发言模式(中文优化)"""
+    analysis = {
+        "word_count": len(speech),
+        "confidence_keywords": 0,
+        "doubt_keywords": 0,
+        "emotion_score": 0
+    }
+    
+    # 中文关键词分析
+    confidence_words = ["确定", "肯定", "一定", "绝对", "必须", "显然"]
+    doubt_words = ["可能", "也许", "或许", "怀疑", "不确定", "感觉"]
+    
+    for word in confidence_words:
+        analysis["confidence_keywords"] += speech.count(word)
+    
+    for word in doubt_words:
+        analysis["doubt_keywords"] += speech.count(word)
+    
+    # 简单情感分析
+    positive_words = ["好", "棒", "赞", "支持", "同意"]
+    negative_words = ["坏", "差", "反对", "不行", "错误"]
+    
+    for word in positive_words:
+        analysis["emotion_score"] += speech.count(word)
+    
+    for word in negative_words:
+        analysis["emotion_score"] -= speech.count(word)
+    
+    return analysis
+
+
+class GameModerator(AgentBase):
+    """中文版游戏主持人"""
+    
+    def __init__(self) -> None:
+        super().__init__()
+        self.name = "游戏主持人"
+        self.game_log: List[str] = []
+    
+    async def announce(self, content: str) -> Msg:
+        """发布游戏公告"""
+        msg = Msg(
+            name=self.name,
+            content=f"📢 {content}",
+            role="system"
+        )
+        self.game_log.append(content)
+        await self.print(msg)
+        return msg
+    
+    async def night_announcement(self, round_num: int) -> Msg:
+        """夜晚阶段公告"""
+        content = f"🌙 第{round_num}夜降临,天黑请闭眼..."
+        return await self.announce(content)
+    
+    async def day_announcement(self, round_num: int) -> Msg:
+        """白天阶段公告"""
+        content = f"☀️ 第{round_num}天天亮了,请大家睁眼..."
+        return await self.announce(content)
+    
+    async def death_announcement(self, dead_players: List[str]) -> Msg:
+        """死亡公告"""
+        if not dead_players:
+            content = "昨夜平安无事,无人死亡。"
+        else:
+            content = f"昨夜,{format_player_list_str(dead_players)}不幸遇害。"
+        return await self.announce(content)
+    
+    async def vote_result_announcement(self, voted_out: str, vote_count: int) -> Msg:
+        """投票结果公告"""
+        content = f"投票结果:{voted_out}以{vote_count}票被淘汰出局。"
+        return await self.announce(content)
+    
+    async def game_over_announcement(self, winner: str) -> Msg:
+        """游戏结束公告"""
+        content = f"🎉 游戏结束!{winner}"
+        return await self.announce(content)
+
+
+def format_player_list_str(players: List[str]) -> str:
+    """格式化玩家姓名列表"""
+    if not players:
+        return "无人"
+    return "、".join(players)
+
+
+def calculate_suspicion_score(player_name: str, game_history: List[Dict]) -> float:
+    """计算玩家可疑度分数"""
+    score = 0.0
+    
+    for event in game_history:
+        if event.get("type") == "vote" and event.get("target") == player_name:
+            score += 0.3
+        elif event.get("type") == "accusation" and event.get("target") == player_name:
+            score += 0.2
+        elif event.get("type") == "defense" and event.get("player") == player_name:
+            score -= 0.1
+    
+    return min(max(score, 0.0), 1.0)
+
+
+async def handle_interrupt(*args: Any, **kwargs: Any) -> Msg:
+    """处理游戏中断"""
+    return Msg(
+        name="系统",
+        content="游戏被中断",
+        role="system"
+    )

+ 4 - 0
code/chapter6/AutoGenDemo/.env copy

@@ -0,0 +1,4 @@
+LLM_MODEL_ID="YOUR-MODEL"
+LLM_API_KEY="YOUR-API-KEY"
+LLM_BASE_URL="YOUR-URL"
+LLM_TIMEOUT=60

+ 199 - 0
code/chapter6/AutoGenDemo/README.md

@@ -0,0 +1,199 @@
+# AutoGen 软件开发团队协作案例
+
+本目录包含第六章 AutoGen 框架的完整实战案例,展示了如何使用 AutoGen 构建多智能体协作的软件开发团队。
+
+## 📁 文件说明
+
+- `autogen_software_team.py` - 主要案例代码(基于 OpenAI 客户端)
+- `llm_client.py` - HelloAgentsLLM 客户端实现
+- `requirements.txt` - 依赖包列表
+- `output.py` - 团队协作生成的比特币价格应用示例
+- `README.md` - 本说明文档
+
+## 🚀 案例特点
+
+- **多智能体协作**:演示产品经理、工程师、代码审查员、用户代理的完整协作流程
+- **真实开发场景**:从需求分析到代码实现的完整软件开发生命周期
+- **自动化流程**:智能体间自动传递任务,无需人工干预
+- **代码生成与审查**:自动生成可运行的代码并进行质量审查
+
+## 🛠️ 环境准备
+
+### 1. 安装依赖
+
+```bash
+pip install -r requirements.txt
+```
+
+### 2. 配置环境变量
+
+创建 `.env` 文件并配置以下参数:
+
+```bash
+# LLM 配置
+LLM_API_KEY=your-api-key-here
+LLM_BASE_URL=https://api.openai.com/v1
+LLM_MODEL_ID=gpt-4
+```
+
+### 3. 验证环境
+
+确保可以正常调用 LLM API:
+
+```python
+import os
+from dotenv import load_dotenv
+load_dotenv()
+
+print(f"API Key: {os.getenv('LLM_API_KEY')[:10]}...")
+print(f"Base URL: {os.getenv('LLM_BASE_URL')}")
+print(f"Model: {os.getenv('LLM_MODEL_ID')}")
+```
+
+## 🎯 运行案例
+
+### 启动软件开发团队协作
+
+```bash
+python autogen_software_team.py
+```
+
+### 预期输出流程
+
+1. **🔧 模型客户端初始化**
+2. **👥 智能体团队创建**
+3. **🚀 团队协作启动**
+4. **💬 智能体对话过程**:
+   - ProductManager:需求分析和技术规划
+   - Engineer:代码实现
+   - CodeReviewer:代码审查和优化建议
+   - UserProxy:用户测试和反馈
+5. **✅ 协作完成**
+
+## 👥 智能体角色说明
+
+### 🎯 ProductManager(产品经理)
+- **职责**:需求分析、技术规划、风险评估
+- **输出**:功能模块划分、技术选型建议、验收标准
+- **特点**:注重用户体验和产品可行性
+
+### 💻 Engineer(软件工程师)
+- **职责**:代码实现、技术方案设计
+- **输出**:完整的可运行代码
+- **特点**:精通 Python、Streamlit、API 集成
+
+### 🔍 CodeReviewer(代码审查员)
+- **职责**:代码质量检查、安全性审查
+- **输出**:代码审查报告、优化建议
+- **特点**:关注代码规范、性能和安全性
+
+### 👤 UserProxy(用户代理)
+- **职责**:代表用户需求、执行测试、提供反馈
+- **输出**:测试结果、用户反馈
+- **特点**:从用户角度验证功能
+
+## 📊 案例演示:比特币价格应用
+
+### 应用功能
+- ✅ 实时显示比特币当前价格(USD)
+- ✅ 显示24小时价格变化趋势
+- ✅ 提供价格刷新功能
+- ✅ 错误处理和加载状态
+- ✅ 简洁美观的 Streamlit 界面
+
+### 技术栈
+- **前端框架**:Streamlit
+- **数据源**:CoinGecko API
+- **编程语言**:Python
+- **HTTP 请求**:requests
+
+### 运行生成的应用
+
+```bash
+streamlit run output.py
+```
+
+## 🔧 自定义配置
+
+### 修改智能体角色
+
+可以通过修改 `system_message` 来自定义智能体的行为:
+
+```python
+def create_product_manager(model_client):
+    system_message = """
+    你是一位经验丰富的产品经理...
+    # 在这里自定义角色描述
+    """
+    return AssistantAgent(
+        name="ProductManager",
+        model_client=model_client,
+        system_message=system_message,
+    )
+```
+
+### 调整协作流程
+
+可以修改参与者列表和终止条件:
+
+```python
+team_chat = RoundRobinGroupChat(
+    participants=[
+        product_manager,
+        engineer, 
+        code_reviewer,
+        user_proxy
+    ],
+    termination_condition=TextMentionTermination("TERMINATE"),
+    max_turns=20,  # 调整最大轮次
+)
+```
+
+## 🐛 常见问题
+
+### Q: 智能体没有开始对话?
+A: 检查以下几点:
+- 确认 API Key 配置正确
+- 检查网络连接
+- 验证模型名称是否正确
+
+### Q: 协作过程中断?
+A: 可能原因:
+- API 调用限制
+- 网络超时
+- 模型响应异常
+
+### Q: 生成的代码无法运行?
+A: 建议:
+- 检查依赖包是否完整安装
+- 验证 API 接口是否可用
+- 查看错误日志进行调试
+
+## 📚 扩展学习
+
+### 相关章节
+- 第四章:智能体经典范式构建
+- 第七章:构建你的Agent框架
+- 第十二章:多智能体协作与通信
+
+### 进阶实践
+- 尝试添加更多智能体角色(如测试工程师、UI设计师)
+- 实现更复杂的应用场景
+- 集成更多的工具和API
+- 优化智能体间的协作策略
+
+## 🤝 贡献指南
+
+欢迎提交 Issue 和 Pull Request 来改进这个案例:
+- 报告 Bug 或问题
+- 提出新的功能建议
+- 分享你的实践经验
+- 优化代码实现
+
+---
+
+*本案例是 Hello-Agents 教程的一部分,更多内容请参考项目主页。*
+
+
+
+

+ 198 - 0
code/chapter6/AutoGenDemo/autogen_software_team.py

@@ -0,0 +1,198 @@
+"""
+AutoGen 软件开发团队协作案例
+"""
+
+import os
+import asyncio
+from typing import List, Dict, Any
+from dotenv import load_dotenv
+
+# 加载环境变量
+load_dotenv()
+
+# # 导入 HelloAgentsLLM
+# import sys
+# sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
+# from llm_client import HelloAgentsLLM
+
+# 先测试一个版本,使用 OpenAI 客户端
+from autogen_ext.models.openai import OpenAIChatCompletionClient
+from autogen_agentchat.agents import AssistantAgent, UserProxyAgent
+from autogen_agentchat.teams import RoundRobinGroupChat
+from autogen_agentchat.conditions import TextMentionTermination
+from autogen_agentchat.ui import Console
+
+def create_openai_model_client():
+    """创建 OpenAI 模型客户端用于测试"""
+    return OpenAIChatCompletionClient(
+        model=os.getenv("LLM_MODEL_ID", "gpt-4o"),
+        api_key=os.getenv("LLM_API_KEY"),
+        base_url=os.getenv("LLM_BASE_URL", "https://api.openai.com/v1")
+    )
+
+def create_product_manager(model_client):
+    """创建产品经理智能体"""
+    system_message = """你是一位经验丰富的产品经理,专门负责软件产品的需求分析和项目规划。
+
+你的核心职责包括:
+1. **需求分析**:深入理解用户需求,识别核心功能和边界条件
+2. **技术规划**:基于需求制定清晰的技术实现路径
+3. **风险评估**:识别潜在的技术风险和用户体验问题
+4. **协调沟通**:与工程师和其他团队成员进行有效沟通
+
+当接到开发任务时,请按以下结构进行分析:
+1. 需求理解与分析
+2. 功能模块划分
+3. 技术选型建议
+4. 实现优先级排序
+5. 验收标准定义
+
+请简洁明了地回应,并在分析完成后说"请工程师开始实现"。"""
+
+    return AssistantAgent(
+        name="ProductManager",
+        model_client=model_client,
+        system_message=system_message,
+    )
+
+def create_engineer(model_client):
+    """创建软件工程师智能体"""
+    system_message = """你是一位资深的软件工程师,擅长 Python 开发和 Web 应用构建。
+
+你的技术专长包括:
+1. **Python 编程**:熟练掌握 Python 语法和最佳实践
+2. **Web 开发**:精通 Streamlit、Flask、Django 等框架
+3. **API 集成**:有丰富的第三方 API 集成经验
+4. **错误处理**:注重代码的健壮性和异常处理
+
+当收到开发任务时,请:
+1. 仔细分析技术需求
+2. 选择合适的技术方案
+3. 编写完整的代码实现
+4. 添加必要的注释和说明
+5. 考虑边界情况和异常处理
+
+请提供完整的可运行代码,并在完成后说"请代码审查员检查"。"""
+
+    return AssistantAgent(
+        name="Engineer",
+        model_client=model_client,
+        system_message=system_message,
+    )
+
+def create_code_reviewer(model_client):
+    """创建代码审查员智能体"""
+    system_message = """你是一位经验丰富的代码审查专家,专注于代码质量和最佳实践。
+
+你的审查重点包括:
+1. **代码质量**:检查代码的可读性、可维护性和性能
+2. **安全性**:识别潜在的安全漏洞和风险点
+3. **最佳实践**:确保代码遵循行业标准和最佳实践
+4. **错误处理**:验证异常处理的完整性和合理性
+
+审查流程:
+1. 仔细阅读和理解代码逻辑
+2. 检查代码规范和最佳实践
+3. 识别潜在问题和改进点
+4. 提供具体的修改建议
+5. 评估代码的整体质量
+
+请提供具体的审查意见,完成后说"代码审查完成,请用户代理测试"。"""
+
+    return AssistantAgent(
+        name="CodeReviewer",
+        model_client=model_client,
+        system_message=system_message,
+    )
+
+def create_user_proxy():
+    """创建用户代理智能体"""
+    return UserProxyAgent(
+        name="UserProxy",
+        description="""用户代理,负责以下职责:
+1. 代表用户提出开发需求
+2. 执行最终的代码实现
+3. 验证功能是否符合预期
+4. 提供用户反馈和建议
+
+完成测试后请回复 TERMINATE。""",
+    )
+
+async def run_software_development_team():
+    """运行软件开发团队协作"""
+    
+    print("🔧 正在初始化模型客户端...")
+    
+    # 先使用标准的 OpenAI 客户端测试
+    model_client = create_openai_model_client()
+    
+    print("👥 正在创建智能体团队...")
+    
+    # 创建智能体团队
+    product_manager = create_product_manager(model_client)
+    engineer = create_engineer(model_client)
+    code_reviewer = create_code_reviewer(model_client)
+    user_proxy = create_user_proxy()
+    
+    # 添加终止条件
+    termination = TextMentionTermination("TERMINATE")
+    
+    # 创建团队聊天
+    team_chat = RoundRobinGroupChat(
+        participants=[
+            product_manager,
+            engineer, 
+            code_reviewer,
+            user_proxy
+        ],
+        termination_condition=termination,
+        max_turns=20,  # 增加最大轮次
+    )
+    
+    # 定义开发任务
+    task = """我们需要开发一个比特币价格显示应用,具体要求如下:
+
+核心功能:
+- 实时显示比特币当前价格(USD)
+- 显示24小时价格变化趋势(涨跌幅和涨跌额)
+- 提供价格刷新功能
+
+技术要求:
+- 使用 Streamlit 框架创建 Web 应用
+- 界面简洁美观,用户友好
+- 添加适当的错误处理和加载状态
+
+请团队协作完成这个任务,从需求分析到最终实现。"""
+    
+    # 执行团队协作
+    print("🚀 启动 AutoGen 软件开发团队协作...")
+    print("=" * 60)
+    
+    # 使用 Console 来显示对话过程
+    result = await Console(team_chat.run_stream(task=task))
+    
+    print("\n" + "=" * 60)
+    print("✅ 团队协作完成!")
+    
+    return result
+
+# 主程序入口
+if __name__ == "__main__":
+    try:
+        # 运行异步协作流程
+        result = asyncio.run(run_software_development_team())
+        
+        print(f"\n📋 协作结果摘要:")
+        print(f"- 参与智能体数量:4个")
+        print(f"- 任务完成状态:{'成功' if result else '需要进一步处理'}")
+        
+    except ValueError as e:
+        print(f"❌ 配置错误:{e}")
+        print("请检查 .env 文件中的配置是否正确")
+    except Exception as e:
+        print(f"❌ 运行错误:{e}")
+        import traceback
+        traceback.print_exc()
+
+
+

+ 72 - 0
code/chapter6/AutoGenDemo/llm_client.py

@@ -0,0 +1,72 @@
+import os
+from openai import OpenAI
+from dotenv import load_dotenv
+from typing import List, Dict
+
+# 加载 .env 文件中的环境变量
+load_dotenv()
+
+class HelloAgentsLLM:
+    """
+    为本书 "Hello Agents" 定制的LLM客户端。
+    它用于调用任何兼容OpenAI接口的服务,并默认使用流式响应。
+    """
+    def __init__(self, model: str = None, apiKey: str = None, baseUrl: str = None, timeout: int = None):
+        """
+        初始化客户端。优先使用传入参数,如果未提供,则从环境变量加载。
+        """
+        self.model = model or os.getenv("LLM_MODEL_ID")
+        apiKey = apiKey or os.getenv("LLM_API_KEY")
+        baseUrl = baseUrl or os.getenv("LLM_BASE_URL")
+        timeout = timeout or int(os.getenv("LLM_TIMEOUT", 60))
+        
+        if not all([self.model, apiKey, baseUrl]):
+            raise ValueError("模型ID、API密钥和服务地址必须被提供或在.env文件中定义。")
+
+        self.client = OpenAI(api_key=apiKey, base_url=baseUrl, timeout=timeout)
+
+    def think(self, messages: List[Dict[str, str]], temperature: float = 0) -> str:
+        """
+        调用大语言模型进行思考,并返回其响应。
+        """
+        print(f"🧠 正在调用 {self.model} 模型...")
+        try:
+            response = self.client.chat.completions.create(
+                model=self.model,
+                messages=messages,
+                temperature=temperature,
+                stream=True,
+            )
+            
+            # 处理流式响应
+            print("✅ 大语言模型响应成功:")
+            collected_content = []
+            for chunk in response:
+                content = chunk.choices[0].delta.content or ""
+                print(content, end="", flush=True)
+                collected_content.append(content)
+            print()  # 在流式输出结束后换行
+            return "".join(collected_content)
+
+        except Exception as e:
+            print(f"❌ 调用LLM API时发生错误: {e}")
+            return None
+
+# --- 客户端使用示例 ---
+if __name__ == '__main__':
+    try:
+        llmClient = HelloAgentsLLM()
+        
+        exampleMessages = [
+            {"role": "system", "content": "You are a helpful assistant that writes Python code."},
+            {"role": "user", "content": "写一个快速排序算法"}
+        ]
+        
+        print("--- 调用LLM ---")
+        responseText = llmClient.think(exampleMessages)
+        if responseText:
+            print("\n\n--- 完整模型响应 ---")
+            print(responseText)
+
+    except ValueError as e:
+        print(e)

+ 39 - 0
code/chapter6/AutoGenDemo/output.py

@@ -0,0 +1,39 @@
+import streamlit as st
+import requests
+import json
+
+# 数据获取函数
+def get_bitcoin_price():
+    try:
+        # 获取 Bitcoin 的价格数据
+        response = requests.get('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true')
+        data = response.json()
+        # 获取当前价格和24小时变化
+        current_price = data['bitcoin']['usd']
+        price_change_percentage = data['bitcoin']['usd_24h_change']
+
+        return current_price, price_change_percentage
+    except requests.exceptions.RequestException as e:
+        st.error(f"Error fetching data: {e}")
+        return None, None
+
+# 初始化 Streamlit 应用
+st.title('实时比特币价格')
+st.subheader('获取最新的比特币价格信息及其24小时价格变化趋势')
+
+# 添加刷新按钮
+if st.button('刷新价格'):
+    st.experimental_rerun()
+
+# 显示加载状态
+with st.spinner('加载中...'):
+    current_price, price_change_percentage = get_bitcoin_price()
+
+# 显示数据
+if current_price is not None:
+    st.metric(label="当前比特币价格 (USD)", value=f"${current_price}")
+
+    if price_change_percentage is not None:
+        st.metric(label="24小时变化 (%)", value=f"{price_change_percentage:.2f}%")
+else:
+    st.error("无法获取数据,请稍后重试。")

+ 10 - 0
code/chapter6/AutoGenDemo/requirements.txt

@@ -0,0 +1,10 @@
+# AutoGen 软件开发团队案例依赖 (v0.7.4)
+"autogen-agentchat"
+"autogen-ext[openai,azure]"
+openai>=1.0.0
+streamlit>=1.28.0
+requests>=2.31.0
+pandas>=2.0.0
+plotly>=5.15.0
+asyncio
+dotenv

+ 45 - 0
code/chapter6/CAMEL/DigitalBookWriting.py

@@ -0,0 +1,45 @@
+from colorama import Fore
+from camel.societies import RolePlaying
+from camel.utils import print_text_animated
+
+# 定义协作任务
+task_prompt = """
+创作一本关于"拖延症心理学"的短篇电子书,目标读者是对心理学感兴趣的普通大众。
+要求:
+1. 内容科学严谨,基于实证研究
+2. 语言通俗易懂,避免过多专业术语
+3. 包含实用的改善建议和案例分析
+4. 篇幅控制在8000-10000字
+5. 结构清晰,包含引言、核心章节和总结
+"""
+
+print(Fore.YELLOW + f"协作任务:\n{task_prompt}\n")
+
+# 初始化角色扮演会话
+role_play_session = RolePlaying(
+    assistant_role_name="心理学家", 
+    user_role_name="作家", 
+    task_prompt=task_prompt
+)
+
+print(Fore.CYAN + f"具体任务描述:\n{role_play_session.task_prompt}\n")
+
+# 开始协作对话
+chat_turn_limit, n = 30, 0
+input_msg = role_play_session.init_chat()
+
+while n < chat_turn_limit:
+    n += 1
+    assistant_response, user_response = role_play_session.step(input_msg)
+    
+    print_text_animated(Fore.BLUE + f"作家:\n\n{user_response.msg.content}\n")
+    print_text_animated(Fore.GREEN + f"心理学家:\n\n{assistant_response.msg.content}\n")
+    
+    # 检查任务完成标志
+    if "CAMEL_TASK_DONE" in user_response.msg.content:
+        print(Fore.MAGENTA + "✅ 电子书创作完成!")
+        break
+    
+    input_msg = assistant_response.msg
+
+print(Fore.YELLOW + f"总共进行了 {n} 轮协作对话")

+ 1 - 0
code/chapter6/CAMEL/requirements.txt

@@ -0,0 +1 @@
+camel-ai==0.2.75

+ 259 - 0
code/chapter6/Langgraph/Dialogue_System.py

@@ -0,0 +1,259 @@
+"""
+智能搜索助手 - 基于 LangGraph + Tavily API 的真实搜索系统
+1. 理解用户需求
+2. 使用Tavily API真实搜索信息  
+3. 生成基于搜索结果的回答
+"""
+
+import asyncio
+from typing import TypedDict, Annotated
+from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
+from langchain_openai import ChatOpenAI
+from langgraph.graph import StateGraph, START, END
+from langgraph.graph.message import add_messages
+from langgraph.checkpoint.memory import InMemorySaver
+import os
+from dotenv import load_dotenv
+from tavily import TavilyClient
+
+# 加载环境变量
+load_dotenv()
+
+# 定义状态结构
+class SearchState(TypedDict):
+    messages: Annotated[list, add_messages]
+    user_query: str        # 用户查询
+    search_query: str      # 优化后的搜索查询
+    search_results: str    # Tavily搜索结果
+    final_answer: str      # 最终答案
+    step: str             # 当前步骤
+
+# 初始化模型和Tavily客户端
+llm = ChatOpenAI(
+    model=os.getenv("LLM_MODEL_ID", "gpt-4o-mini"),
+    api_key=os.getenv("LLM_API_KEY"),
+    base_url=os.getenv("LLM_BASE_URL", "https://api.openai.com/v1"),
+    temperature=0.7
+)
+
+# 初始化Tavily客户端
+tavily_client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
+
+def understand_query_node(state: SearchState) -> SearchState:
+    """步骤1:理解用户查询并生成搜索关键词"""
+    
+    # 获取最新的用户消息
+    user_message = ""
+    for msg in reversed(state["messages"]):
+        if isinstance(msg, HumanMessage):
+            user_message = msg.content
+            break
+    
+    understand_prompt = f"""分析用户的查询:"{user_message}"
+
+请完成两个任务:
+1. 简洁总结用户想要了解什么
+2. 生成最适合搜索的关键词(中英文均可,要精准)
+
+格式:
+理解:[用户需求总结]
+搜索词:[最佳搜索关键词]"""
+
+    response = llm.invoke([SystemMessage(content=understand_prompt)])
+    
+    # 提取搜索关键词
+    response_text = response.content
+    search_query = user_message  # 默认使用原始查询
+    
+    if "搜索词:" in response_text:
+        search_query = response_text.split("搜索词:")[1].strip()
+    elif "搜索关键词:" in response_text:
+        search_query = response_text.split("搜索关键词:")[1].strip()
+    
+    return {
+        "user_query": response.content,
+        "search_query": search_query,
+        "step": "understood",
+        "messages": [AIMessage(content=f"我理解您的需求:{response.content}")]
+    }
+
+def tavily_search_node(state: SearchState) -> SearchState:
+    """步骤2:使用Tavily API进行真实搜索"""
+    
+    search_query = state["search_query"]
+    
+    try:
+        print(f"🔍 正在搜索: {search_query}")
+        
+        # 调用Tavily搜索API
+        response = tavily_client.search(
+            query=search_query,
+            search_depth="basic",
+            include_answer=True,
+            include_raw_content=False,
+            max_results=5
+        )
+        
+        # 处理搜索结果
+        search_results = ""
+        
+        # 优先使用Tavily的综合答案
+        if response.get("answer"):
+            search_results = f"综合答案:\n{response['answer']}\n\n"
+        
+        # 添加具体的搜索结果
+        if response.get("results"):
+            search_results += "相关信息:\n"
+            for i, result in enumerate(response["results"][:3], 1):
+                title = result.get("title", "")
+                content = result.get("content", "")
+                url = result.get("url", "")
+                search_results += f"{i}. {title}\n{content}\n来源:{url}\n\n"
+        
+        if not search_results:
+            search_results = "抱歉,没有找到相关信息。"
+        
+        return {
+            "search_results": search_results,
+            "step": "searched",
+            "messages": [AIMessage(content=f"✅ 搜索完成!找到了相关信息,正在为您整理答案...")]
+        }
+        
+    except Exception as e:
+        error_msg = f"搜索时发生错误: {str(e)}"
+        print(f"❌ {error_msg}")
+        
+        return {
+            "search_results": f"搜索失败:{error_msg}",
+            "step": "search_failed",
+            "messages": [AIMessage(content="❌ 搜索遇到问题,我将基于已有知识为您回答")]
+        }
+
+def generate_answer_node(state: SearchState) -> SearchState:
+    """步骤3:基于搜索结果生成最终答案"""
+    
+    # 检查是否有搜索结果
+    if state["step"] == "search_failed":
+        # 如果搜索失败,基于LLM知识回答
+        fallback_prompt = f"""搜索API暂时不可用,请基于您的知识回答用户的问题:
+
+用户问题:{state['user_query']}
+
+请提供一个有用的回答,并说明这是基于已有知识的回答。"""
+        
+        response = llm.invoke([SystemMessage(content=fallback_prompt)])
+        
+        return {
+            "final_answer": response.content,
+            "step": "completed",
+            "messages": [AIMessage(content=response.content)]
+        }
+    
+    # 基于搜索结果生成答案
+    answer_prompt = f"""基于以下搜索结果为用户提供完整、准确的答案:
+
+用户问题:{state['user_query']}
+
+搜索结果:
+{state['search_results']}
+
+请要求:
+1. 综合搜索结果,提供准确、有用的回答
+2. 如果是技术问题,提供具体的解决方案或代码
+3. 引用重要信息的来源
+4. 回答要结构清晰、易于理解
+5. 如果搜索结果不够完整,请说明并提供补充建议"""
+
+    response = llm.invoke([SystemMessage(content=answer_prompt)])
+    
+    return {
+        "final_answer": response.content,
+        "step": "completed",
+        "messages": [AIMessage(content=response.content)]
+    }
+
+# 构建搜索工作流
+def create_search_assistant():
+    workflow = StateGraph(SearchState)
+    
+    # 添加三个节点
+    workflow.add_node("understand", understand_query_node)
+    workflow.add_node("search", tavily_search_node)
+    workflow.add_node("answer", generate_answer_node)
+    
+    # 设置线性流程
+    workflow.add_edge(START, "understand")
+    workflow.add_edge("understand", "search")
+    workflow.add_edge("search", "answer")
+    workflow.add_edge("answer", END)
+    
+    # 编译图
+    memory = InMemorySaver()
+    app = workflow.compile(checkpointer=memory)
+    
+    return app
+
+async def main():
+    """主函数:运行智能搜索助手"""
+    
+    # 检查API密钥
+    if not os.getenv("TAVILY_API_KEY"):
+        print("❌ 错误:请在.env文件中配置TAVILY_API_KEY")
+        return
+    
+    app = create_search_assistant()
+    
+    print("🔍 智能搜索助手启动!")
+    print("我会使用Tavily API为您搜索最新、最准确的信息")
+    print("支持各种问题:新闻、技术、知识问答等")
+    print("(输入 'quit' 退出)\n")
+    
+    session_count = 0
+    
+    while True:
+        user_input = input("🤔 您想了解什么: ").strip()
+        
+        if user_input.lower() in ['quit', 'q', '退出', 'exit']:
+            print("感谢使用!再见!👋")
+            break
+        
+        if not user_input:
+            continue
+        
+        session_count += 1
+        config = {"configurable": {"thread_id": f"search-session-{session_count}"}}
+        
+        # 初始状态
+        initial_state = {
+            "messages": [HumanMessage(content=user_input)],
+            "user_query": "",
+            "search_query": "",
+            "search_results": "",
+            "final_answer": "",
+            "step": "start"
+        }
+        
+        try:
+            print("\n" + "="*60)
+            
+            # 执行工作流
+            async for output in app.astream(initial_state, config=config):
+                for node_name, node_output in output.items():
+                    if "messages" in node_output and node_output["messages"]:
+                        latest_message = node_output["messages"][-1]
+                        if isinstance(latest_message, AIMessage):
+                            if node_name == "understand":
+                                print(f"🧠 理解阶段: {latest_message.content}")
+                            elif node_name == "search":
+                                print(f"🔍 搜索阶段: {latest_message.content}")
+                            elif node_name == "answer":
+                                print(f"\n💡 最终回答:\n{latest_message.content}")
+            
+            print("\n" + "="*60 + "\n")
+        
+        except Exception as e:
+            print(f"❌ 发生错误: {e}")
+            print("请重新输入您的问题。\n")
+
+if __name__ == "__main__":
+    asyncio.run(main())

+ 4 - 0
code/chapter6/Langgraph/requirements.txt

@@ -0,0 +1,4 @@
+langgraph==1.0.0a3
+langchain_openai==0.3.33
+python-dotenv
+tavily-python

+ 4 - 6
docs/README.md

@@ -38,7 +38,7 @@
 | <strong>第二部分:构建你的大语言模型智能体</strong> |  |  |
 | [第四章 智能体经典范式构建](./chapter4/第四章%20智能体经典范式构建.md) | 手把手实现 ReAct、Plan-and-Solve、Reflection | ✅ |
 | [第五章 基于低代码平台的智能体搭建](./chapter5/第五章%20基于低代码平台的智能体搭建.md) | 了解Coze、n8n等商业化低代码智能体平台使用 | 🚧 |
-| [第六章 框架开发实践](./chapter6/第六章%20框架开发实践.md) | AutoGen、AgentScope、LangGraph 等主流框架应用 | 🚧 |
+| [第六章 框架开发实践](./chapter6/第六章%20框架开发实践.md) | AutoGen、AgentScope、LangGraph 等主流框架应用 |  |
 | [第七章 构建你的Agent框架](./chapter7/第七章%20构建你的Agent框架.md) | 从0开始构建智能体框架 | 🚧 |
 | <strong>第三部分:高级知识扩展</strong> |  |  |
 | [第八章 推理与规划](./chapter8/第八章%20推理与规划.md) | CoT, 逻辑推理, 搜索与规划 | 🚧 |
@@ -55,15 +55,13 @@
 
 ### 社区贡献精选 (Community Blog)
 
-&emsp;&emsp;欢迎大家将在学习 Hello-Agents 或 Agent 相关技术中的独到见解、实践总结,以 PR 的形式贡献到社区精选。如果是独立于正文的内容,也可以投稿至Extra-Chapter!
-
-<strong>暂无内容,期待你的第一次贡献!</strong>
+&emsp;&emsp;欢迎大家将在学习 Hello-Agents 或 Agent 相关技术中的独到见解、实践总结,以 PR 的形式贡献到社区精选。如果是独立于正文的内容,也可以投稿至Extra-Chapter!<strong>期待你的第一次贡献!</strong>
 
 ### PDF 版本下载
 
 &emsp;&emsp; *<strong>本 Hello-Agents PDF 教程完全开源免费。为防止各类营销号加水印后贩卖给多智能体系统初学者,我们特地在 PDF 文件中预先添加了不影响阅读的 Datawhale 开源标志水印,敬请谅解~</strong>*
 
-> *Hello-Agents PDF : https://github.com/datawhalechina/Hello-Agents/releases/tag/PDF*  
+> *Hello-Agents PDF : https://github.com/datawhalechina/Hello-Agents/releases/tag/PDF(尚未完成)*  
 > *Hello-Agents PDF 国内下载地址 : https://www.datawhale.cn/learn/summary/XXX* 
 
 ## 💡 如何学习
@@ -118,7 +116,7 @@
 ## Star History
 
 <div align='center'>
-    <img src="./images/star-history-2025913.png" alt="Datawhale" width="90%">
+    <img src="./images/star-history-2025916.png" alt="Datawhale" width="90%">
 </div>
 
 <div align="center">

+ 1279 - 1
docs/chapter6/第六章 框架开发实践.md

@@ -1,3 +1,1281 @@
 # 第六章 框架开发实践
 
-本章内容待补充...
+在第四章中,我们通过编写原生代码,实现了 ReAct、Plan-and-Solve 和 Reflection 这几种智能体的核心工作流。这个过程让我们对智能体的内在执行逻辑有了理解。随后,在第五章,我们切换到“使用者”的视角,体验了低代码平台带来的便捷与高效。
+
+本章的目标,就是探讨如何利用业界主流的一些<strong>智能体框架</strong>,来高效、规范地构建可靠的智能体应用。我们将首先概览当前市面上主流的智能体框架,然后并对几个具有代表性的框架,通过一个完整的实战案例,来体验框架驱动的开发模式。
+
+## 6.1 从手动实现到框架开发
+
+从编写一次性的脚本到使用一个成熟的框架,是软件工程领域一次重要的思维跃迁。我们在第四章中编写的代码,其主要目的是为了教学和理解。它们能很好地完成特定任务,但如果要用它们来构建多个、不同类型且逻辑复杂的智能体应用,很快就会遇到瓶颈。
+
+一个框架的本质,是提供一套经过验证的“规范”。它将所有智能体共有的、重复性的工作(如主循环、状态管理、工具调用、日志记录等)进行抽象和封装,让我们在构建新的智能体时,能够专注于其独特的业务逻辑,而非通用的底层实现。
+
+### 6.1.1 为何需要智能体框架
+
+在我们开始实战之前,首先需要明确为什么要使用框架。相比于直接编写独立的智能体脚本,使用框架的价值主要体现在以下几个方面:
+
+1. <strong>提升代码复用与开发效率</strong>:这是最直接的价值。一个好的框架会提供一个通用的 `Agent` 基类或执行器,它封装了智能体运行的核心循环(Agent Loop)。无论是 ReAct 还是 Plan-and-Solve,都可以基于框架提供的标准组件快速搭建,从而避免重复劳动。
+2. <strong>实现核心组件的解耦与可扩展性</strong>:一个健壮的智能体系统应该由多个松散耦合的模块组成。框架的设计会强制我们分离不同的关注点:
+   - <strong>模型层 (Model Layer)</strong>:负责与大语言模型交互,可以轻松替换不同的模型(OpenAI, Anthropic, 本地模型)。
+   - <strong>工具层 (Tool Layer)</strong>:提供标准化的工具定义、注册和执行接口,添加新工具不会影响其他代码。
+   - <strong>记忆层 (Memory Layer)</strong>:处理短期和长期记忆,可以根据需求切换不同的记忆策略(如滑动窗口、摘要记忆)。 这种模块化的设计使得整个系统极具可扩展性,更换或升级任何一个组件都变得简单。
+3. <strong>标准化复杂的状态管理</strong>:我们在 `ReflectionAgent` 中实现的 `Memory` 类只是一个简单的开始。在真实的、长时运行的智能体应用中,状态管理是一个巨大的挑战,它需要处理上下文窗口限制、历史信息持久化、多轮对话状态跟踪等问题。一个框架可以提供一套强大而通用的状态管理机制,开发者无需每次都重新处理这些复杂问题。
+4. <strong>简化可观测性与调试过程</strong>:当智能体的行为变得复杂时,理解其决策过程变得至关重要。一个精心设计的框架可以内置强大的可观测性能力。例如,通过引入事件回调机制(Callbacks),我们可以在智能体生命周期的关键节点(如 `on_llm_start`, `on_tool_end`, `on_agent_finish`)自动触发日志记录或数据上报,从而轻松地追踪和调试智能体的完整运行轨迹。这远比在代码中手动添加 `print` 语句要高效和系统化。
+
+因此,从手动实现走向框架开发,不仅是代码组织方式的改变,更是构建复杂、可靠、可维护的智能体应用的必由之路。
+
+### 6.1.2 主流框架的选型与对比
+
+智能体框架的生态正在以前所未有的速度发展。如果说 LangChain 和 LlamaIndex 定义了第一代通用 LLM 应用框架的范式,那么新一代的框架则更加专注于解决特定领域的深层挑战,尤其是<strong>多智能体协作 (Multi-Agent Collaboration)</strong> 和 <strong>复杂工作流控制 (Complex Workflow Control)</strong>。
+
+在本章的后续实战中,我们将聚焦于四个在这些前沿领域极具代表性的框架:AutoGen、AgentScope、CAMEL 和 LangGraph。它们的设计理念各不相同,分别代表了实现复杂智能体系统的不同技术路径,如图6.1所示。
+
+<div align="center">
+  <p>表 6.1 四种智能体框架对比</p>
+  <img src="https://raw.githubusercontent.com/datawhalechina/Hello-Agents/main/docs/images/6-figures/01.png" alt="" width="90%"/>
+</div>
+- <strong>AutoGen</strong>:AutoGen 的核心思想是通过对话实现协作<sup>[1]</sup>。它将多智能体系统抽象为一个由多个“可对话”智能体组成的群聊。开发者可以定义不同角色(如 `Coder`, `ProductManager`, `Tester`),并设定它们之间的交互规则(例如,`Coder` 写完代码后由 `Tester` 自动接管)。任务的解决过程,就是这些智能体在群聊中通过自动化消息传递,不断对话、协作、迭代直至最终目标达成的过程。
+- <strong>AgentScope</strong>:AgentScope 是一个专为多智能体应用设计的、功能全面的开发平台<sup>[2]</sup>。它的核心特点是<strong>易用性</strong>和<strong>工程化</strong>。它提供了一套非常友好的编程接口,让开发者可以轻松定义智能体、构建通信网络,并管理整个应用的生命周期。其内置的<strong>消息传递机制</strong>和对分布式部署的支持,使其非常适合构建和运维复杂、大规模的多智能体系统。
+- <strong>CAMEL</strong>:CAMEL 提供了一种新颖的、名为<strong>角色扮演 (Role-Playing)</strong> 的协作方法<sup>[3]</sup>。其核心理念是,我们只需要为两个智能体(例如,`AI研究员` 和 `Python程序员`)设定好各自的角色和共同的任务目标,它们就能在“<strong>初始提示 (Inception Prompting)</strong>”的引导下,自主地进行多轮对话,相互启发、相互配合,共同完成任务。它极大地降低了设计多智能体对话流程的复杂度。
+- <strong>LangGraph</strong>:作为 LangChain 生态的扩展,LangGraph 另辟蹊径,将智能体的执行流程建模为<strong>图 (Graph)</strong><sup>[4]</sup>。在传统的链式结构中,信息只能单向流动。而 LangGraph 将每一步操作(如调用LLM、执行工具)定义为图中的一个<strong>节点 (Node)</strong>,并用<strong>边 (Edge)</strong> 来定义节点之间的跳转逻辑。这种设计天然支持<strong>循环 (Cycles)</strong>,使得实现如 Reflection 这样的迭代、修正、自我反思的复杂工作流变得异常简单和直观。
+
+在接下来的小节中,我们将对这四个框架,分别通过一个完整的实战案例,来深入体验框架驱动的开发模式。<strong>请注意</strong>,所有演示的项目源文件会放在`code`文件夹下,正文内只讲解原理部分。
+
+## 6.2 框架一:AutoGen
+
+正如前文所述,AutoGen 的设计哲学根植于"以对话驱动协作"。它巧妙地将复杂的任务解决流程,映射为不同角色的智能体之间的一系列自动化对话。基于这一核心理念,AutoGen 框架持续演进。我们将以 `0.7.4` 版本为例,因为它是截止目前为止最新版本,代表了一次重要的架构重构,从类继承设计转向了更灵活的组合式架构。为了深入理解并应用这一框架,我们首先需要讲解其最核心的构成要素与底层的对话交互机制。
+
+### 6.2.1 AutoGen 的核心机制
+
+`0.7.4` 版本的发布是 AutoGen 发展的一个重要节点,它标志着框架在底层设计上的一次根本性革新。这次更新并非简单的功能叠加,而是对整体架构的重新思考,旨在提升框架的模块化、并发性能和开发者体验。
+
+<div align="center">
+  <img src="https://raw.githubusercontent.com/datawhalechina/Hello-Agents/main/docs/images/6-figures/02.png" alt="" width="90%"/>
+  <p>图 6.1 AutoGen架构图</p>
+</div>
+
+(1)框架结构的演进
+
+如图6.1所示,新架构最显著的变化是引入了清晰的分层和异步优先的设计理念。
+
+- <strong>分层设计:</strong> 框架被拆分为两个核心模块:
+  - `autogen-core`:作为框架的底层基础,封装了与语言模型交互、消息传递等核心功能。它的存在保证了框架的稳定性和未来扩展性。
+  - `autogen-agentchat`:构建于 `core` 之上,提供了用于开发对话式智能体应用的高级接口,简化了多智能体应用的开发流程。 这种分层策略使得各组件职责明确,降低了系统的耦合度。
+- <strong>异步优先:</strong> 新架构全面转向异步编程 (`async/await`)。在多智能体协作场景中,网络请求(如调用 LLM API)是主要耗时操作。异步模式允许系统在等待一个智能体响应时处理其他任务,从而避免了线程阻塞,显著提升了并发处理能力和系统资源的利用效率。
+
+(2)核心智能体组件
+
+智能体是执行任务的基本单元。在 `0.7.4` 版本中,智能体的设计更加专注和模块化。
+
+- <strong>AssistantAgent (助理智能体):</strong> 这是任务的主要解决者,其核心是封装了一个大型语言模型(LLM)。它的职责是根据对话历史生成富有逻辑和知识的回复,例如提出计划、撰写文章或编写代码。通过不同的系统消息(System Message),我们可以为其赋予不同的“专家”角色。
+- <strong>UserProxyAgent (用户代理智能体):</strong> 这是 AutoGen 中功能独特的组件。它扮演着双重角色:既是人类用户的“代言人”,负责发起任务和传达意图;又是一个可靠的“执行器”,可以配置为执行代码或调用工具,并将结果反馈给其他智能体。这种设计清晰地区分了“思考”(由 `AssistantAgent` 完成)与“行动”。
+
+(3)从 GroupChatManager 到 Team
+
+当任务需要多个智能体协作时,就需要一个机制来协调对话流程。在早期版本中,`GroupChatManager` 承担了这一职责。而在新架构中,引入了更灵活的 `Team` 或群聊概念,例如 `RoundRobinGroupChat`。
+
+- <strong>轮询群聊 (RoundRobinGroupChat):</strong> 这是一种明确的、顺序化的对话协调机制。它会让参与的智能体按照预定义的顺序依次发言。这种模式非常适用于流程固定的任务,例如一个典型的软件开发流程:产品经理先提出需求,然后工程师编写代码,最后由代码审查员进行检查。
+- <strong>工作流:</strong>
+  1. 首先,创建一个 `RoundRobinGroupChat` 实例,并将所有参与协作的智能体(如产品经理、工程师等)加入其中。
+  2. 当一个任务开始时,群聊会按照预设的顺序,依次激活相应的智能体。
+  3. 被选中的智能体根据当前的对话上下文进行响应。
+  4. 群聊将新的回复加入对话历史,并激活下一个智能体。
+  5. 这个过程会持续进行,直到达到最大对话轮次或满足预设的终止条件。
+
+通过这种方式,AutoGen 将复杂的协作关系,简化为一个流程清晰、易于管理的自动化“圆桌会议”。开发者只需定义好每个团队成员的角色和发言顺序,剩下的协作流程便可由群聊机制自主驱动。
+
+在下一节中,我们将通过构建一个模拟软件开发团队的实例,来亲身体验如何在新架构下定义不同角色的智能体,并将它们组织在一个由 `RoundRobinGroupChat` 协调的群聊中,以协作完成一个真实的编程任务。
+
+### 6.2.2 软件开发团队
+
+在理解了 AutoGen 的核心组件与对话机制后,本节将通过一个完整的实战案例来具体展示如何应用这些新特性。我们将构建一个模拟的软件开发团队,该团队由多个具有不同专业技能的智能体组成,它们将协作完成一个真实的软件开发任务。
+
+(1)业务目标
+
+我们的目标是开发一个功能明确的 Web 应用:<strong>实时显示比特币当前价格</strong>。这个任务虽小,却完整地覆盖了软件开发的典型环节:从需求分析、技术选型、编码实现到代码审查和最终测试。这使其成为检验 AutoGen 自动化协作流程的理想场景。
+
+(2)智能体团队角色
+
+为了模拟真实的软件开发流程,我们设计了四个职责分明的智能体角色:
+
+- <strong>ProductManager (产品经理):</strong> 负责将用户的模糊需求转化为清晰、可执行的开发计划。
+- <strong>Engineer (工程师):</strong> 依据开发计划,负责编写具体的应用程序代码。
+- <strong>CodeReviewer (代码审查员):</strong> 负责审查工程师提交的代码,确保其质量、可读性和健壮性。
+- <strong>UserProxy (用户代理):</strong> 代表最终用户,发起初始任务,并负责执行和验证最终交付的代码。
+
+这种角色划分是多智能体系统设计中的关键一步,它将一个复杂任务分解为多个由领域“专家”处理的子任务。
+
+### 6.2.3 核心代码实现
+
+下面,我们将分步解析这个自动化团队的核心代码。
+
+(1)模型客户端配置
+
+所有基于 LLM 的智能体都需要一个模型客户端来与语言模型进行交互。AutoGen `0.7.4` 提供了标准化的 `OpenAIChatCompletionClient`,它可以方便地与任何兼容 OpenAI API 规范的模型服务(包括 OpenAI 官方服务、Azure OpenAI 以及本地模型服务如 Ollama等)进行对接。
+
+我们通过一个独立的函数来创建和配置模型客户端,并通过环境变量管理 API Key 和服务地址,这是一种良好的工程实践,增强了代码的灵活性和安全性。
+
+```python
+from autogen_ext.models.openai import OpenAIChatCompletionClient
+
+def create_openai_model_client():
+    """创建并配置 OpenAI 模型客户端"""
+    return OpenAIChatCompletionClient(
+        model=os.getenv("LLM_MODEL_ID", "gpt-4o"),
+        api_key=os.getenv("LLM_API_KEY"),
+        base_url=os.getenv("LLM_BASE_URL", "https://api.openai.com/v1")
+    )
+```
+
+(2)智能体角色的定义
+
+定义智能体的核心在于编写高质量的系统消息 (System Message)。系统消息就像是给智能体设定的“行为准则”和“专业知识库”,它精确地规定了智能体的角色、职责、工作流程,甚至是与其他智能体交互的方式。一个精心设计的系统消息是确保多智能体系统能够高效、准确协作的关键。在我们的软件开发团队中,我们为每一个角色都创建了一个独立的函数来封装其定义。
+
+<strong>产品经理 (ProductManager)</strong>
+
+产品经理负责启动整个流程。它的系统消息不仅定义了其职责,还规范了其输出的结构,并包含了引导对话转向下一环节(工程师)的明确指令。
+
+```python
+def create_product_manager(model_client):
+    """创建产品经理智能体"""
+    system_message = """你是一位经验丰富的产品经理,专门负责软件产品的需求分析和项目规划。
+
+你的核心职责包括:
+1. **需求分析**:深入理解用户需求,识别核心功能和边界条件
+2. **技术规划**:基于需求制定清晰的技术实现路径
+3. **风险评估**:识别潜在的技术风险和用户体验问题
+4. **协调沟通**:与工程师和其他团队成员进行有效沟通
+
+当接到开发任务时,请按以下结构进行分析:
+1. 需求理解与分析
+2. 功能模块划分
+3. 技术选型建议
+4. 实现优先级排序
+5. 验收标准定义
+
+请简洁明了地回应,并在分析完成后说"请工程师开始实现"。"""
+
+    return AssistantAgent(
+        name="ProductManager",
+        model_client=model_client,
+        system_message=system_message,
+    )
+```
+
+<strong>工程师 (Engineer)</strong>
+
+工程师的系统消息聚焦于技术实现。它列举了工程师的技术专长,并规定了其在接收到任务后的具体行动步骤,同样也包含了引导流程转向代码审查员的指令。
+
+```python
+def create_engineer(model_client):
+    """创建软件工程师智能体"""
+    system_message = """你是一位资深的软件工程师,擅长 Python 开发和 Web 应用构建。
+
+你的技术专长包括:
+1. **Python 编程**:熟练掌握 Python 语法和最佳实践
+2. **Web 开发**:精通 Streamlit、Flask、Django 等框架
+3. **API 集成**:有丰富的第三方 API 集成经验
+4. **错误处理**:注重代码的健壮性和异常处理
+
+当收到开发任务时,请:
+1. 仔细分析技术需求
+2. 选择合适的技术方案
+3. 编写完整的代码实现
+4. 添加必要的注释和说明
+5. 考虑边界情况和异常处理
+
+请提供完整的可运行代码,并在完成后说"请代码审查员检查"。"""
+
+    return AssistantAgent(
+        name="Engineer",
+        model_client=model_client,
+        system_message=system_message,
+    )
+```
+
+<strong>代码审查员 (CodeReviewer)</strong>
+
+代码审查员的定义则侧重于代码的质量、安全性和规范性。它的系统消息详细列出了审查的重点和流程,确保了代码交付前的质量关卡。
+
+```python
+def create_code_reviewer(model_client):
+    """创建代码审查员智能体"""
+    system_message = """你是一位经验丰富的代码审查专家,专注于代码质量和最佳实践。
+
+你的审查重点包括:
+1. **代码质量**:检查代码的可读性、可维护性和性能
+2. **安全性**:识别潜在的安全漏洞和风险点
+3. **最佳实践**:确保代码遵循行业标准和最佳实践
+4. **错误处理**:验证异常处理的完整性和合理性
+
+审查流程:
+1. 仔细阅读和理解代码逻辑
+2. 检查代码规范和最佳实践
+3. 识别潜在问题和改进点
+4. 提供具体的修改建议
+5. 评估代码的整体质量
+
+请提供具体的审查意见,完成后说"代码审查完成,请用户代理测试"。"""
+
+    return AssistantAgent(
+        name="CodeReviewer",
+        model_client=model_client,
+        system_message=system_message,
+    )
+```
+
+<strong>用户代理 (UserProxy)</strong>
+
+`UserProxyAgent` 是一个特殊的智能体,它不依赖 LLM 进行回复,而是作为用户在系统中的代理。它的 `description` 字段清晰地描述了其职责,尤其重要的是,它负责在任务最终完成后发出 `TERMINATE` 指令,以正常结束整个协作流程。
+
+```python
+def create_user_proxy():
+    """创建用户代理智能体"""
+    return UserProxyAgent(
+        name="UserProxy",
+        description="""用户代理,负责以下职责:
+1. 代表用户提出开发需求
+2. 执行最终的代码实现
+3. 验证功能是否符合预期
+4. 提供用户反馈和建议
+
+完成测试后请回复 TERMINATE。""",
+    )
+```
+
+通过这四个独立的定义函数,我们不仅构建了一支功能完备的“虚拟团队”,也展示了通过系统消息进行“提示工程” ,是设计高效多智能体应用的核心环节。
+
+(3)定义团队协作流程
+
+在本案例中,软件开发的流程是相对固定的(需求->编码->审查->测试),因此 `RoundRobinGroupChat` (轮询群聊) 是理想的选择。我们按照业务逻辑顺序,将四个智能体加入到参与者列表中。
+
+```python
+from autogen_agentchat.teams import RoundRobinGroupChat
+from autogen_agentchat.conditions import TextMentionTermination
+
+# 定义团队聊天和协作规则
+team_chat = RoundRobinGroupChat(
+    participants=[
+        product_manager,
+        engineer,
+        code_reviewer,
+        user_proxy
+    ],
+    termination_condition=TextMentionTermination("TERMINATE"),
+    max_turns=20,
+)
+```
+
+- <strong>参与者顺序:</strong> `participants` 列表的顺序决定了智能体发言的先后次序。
+- <strong>终止条件:</strong> `termination_condition` 是控制协作流程何时结束的关键。这里我们设定,当任何消息中包含关键词 "TERMINATE" 时,对话便结束。在我们的设计中,这个指令由 `UserProxy` 在完成最终测试后发出。
+- <strong>最大轮次:</strong> `max_turns` 是一个安全阀,用于防止对话陷入无限循环,避免不必要的资源消耗。
+
+(4)启动与运行
+
+由于 AutoGen `0.7.4` 采用异步架构,整个协作流程的启动和运行都在一个异步函数中完成,并最终通过 `asyncio.run()` 来执行。
+
+```python
+async def run_software_development_team():
+    # ... 初始化客户端和智能体 ...
+    
+    # 定义任务描述
+    task = """我们需要开发一个比特币价格显示应用,具体要求如下:
+            核心功能:
+            - 实时显示比特币当前价格(USD)
+            - 显示24小时价格变化趋势(涨跌幅和涨跌额)
+            - 提供价格刷新功能
+
+            技术要求:
+            - 使用 Streamlit 框架创建 Web 应用
+            - 界面简洁美观,用户友好
+            - 添加适当的错误处理和加载状态
+
+            请团队协作完成这个任务,从需求分析到最终实现。"""
+    
+    # 异步执行团队协作,并流式输出对话过程
+    result = await Console(team_chat.run_stream(task=task))
+    return result
+
+# 主程序入口
+if __name__ == "__main__":
+    result = asyncio.run(run_software_development_team())
+```
+
+当程序运行时,`task` 作为初始消息被传入 `team_chat`,产品经理作为第一个参与者接收到该消息,随后整个自动化协作流程便开始了。
+
+(5)预期协作效果
+
+当我们运行这个软件开发团队时,可以观察到一个完整的协作流程:
+
+```bash
+🔧 正在初始化模型客户端...
+👥 正在创建智能体团队...
+🚀 启动 AutoGen 软件开发团队协作...
+============================================================
+---------- TextMessage (user) ----------
+我们需要开发一个比特币价格显示应用,具体要求如下:
+...
+请团队协作完成这个任务,从需求分析到最终实现。
+---------- TextMessage (ProductManager) ----------
+### 1. 需求理解与分析
+...
+请工程师开始实现。
+---------- TextMessage (Engineer) ----------
+### 技术方案实施
+...
+请代码审查员检查。
+---------- TextMessage (CodeReviewer) ----------
+### 代码审查
+...
+代码审查完成,请用户代理测试。    
+---------- TextMessage (UserProxy) ----------
+已经完成需求
+---------- TextMessage (ProductManager) ----------
+太好了,感谢您的反馈!如果在使用过程中有任何问题,或者有其他功能需求和改进建议,请随时告知我们。我们会持续提供支持和改进。期待您对我们的应用
+有愉快的使用体验!
+---------- TextMessage (Engineer) ----------
+很高兴听到项目顺利完成。如果您或用户有任何问题或者需要帮助,请随时联系我们。感谢您对我们工作的支持,让我们一起确保应用稳定运行并不断优化用户
+体验!
+---------- TextMessage (CodeReviewer) ----------
+非常感谢大家的努力与协作,使得项目能够顺利完成。未来若有更多技术支持的需求或者需要改进的地方,我们愿意为项目的持续优化贡
+献力量。期待用户能够享受到流畅的体验,同时也欢迎提出更多的反馈与建议。再次感谢团队的合作!
+---------- TextMessage (UserProxy) ----------
+Enter your response: TERMINATE
+============================================================
+✅ 团队协作完成!
+
+📋 协作结果摘要:
+- 参与智能体数量:4个
+- 任务完成状态:成功
+```
+
+整个协作过程展现了 AutoGen 框架的优势:<strong>自然的对话驱动协作</strong>、<strong>角色专业化分工</strong>、<strong>流程自动化管理</strong>和<strong>完整的开发闭环</strong>。
+
+### 6.2.4 AutoGen 的优势与局限性分析
+
+任何技术框架都有其特定的适用场景和设计权衡。在本节中,我们将客观地分析 AutoGen 的核心优势及其在实际应用中可能面临的局限性与挑战。
+
+(1)优势
+
+- 如案例所示,我们无需为智能体团队设计复杂的状态机或控制流逻辑,而是将一个完整的软件开发流程,自然地映射为产品经理、工程师和审查员之间的对话。这种方式更贴近人类团队的协作模式,显著降低了为复杂任务建模的门槛。开发者可以将更多精力聚焦于定义“谁(角色)”以及“做什么(职责)”,而非“如何做(流程控制)”。
+- 框架允许通过系统消息(System Message)为每个智能体赋予高度专业化的角色。在案例中,`ProductManager` 专注于需求,而 `CodeReviewer` 则专注于质量。一个精心设计的智能体可以在不同项目中被复用,易于维护和扩展。
+- 对于流程化任务,`RoundRobinGroupChat` 这样机制提供了清晰、可预测的协作流程。同时,`UserProxyAgent` 的设计为“人类在环”(Human-in-the-loop)提供了天然的接口。它既可以作为任务的发起者,也可以是流程的监督者和最终的验收者。这种设计确保了自动化系统始终处于人类的监督之下。
+
+(2)局限性
+
+- 虽然 `RoundRobinGroupChat` 提供了顺序化的流程,但基于 LLM 的对话本质上具有不确定性。智能体可能会产生偏离预期的回复,导致对话走向意外的分支,甚至陷入循环。
+- 当智能体团队的工作结果未达预期时,调试过程可能非常棘手。与传统程序不同,我们得到的不是清晰的错误堆栈,而是一长串的对话历史。这被称为“对话式调试”的难题。
+
+
+
+## 6.3 框架二:AgentScope
+
+如果说 AutoGen 的设计哲学是"以对话驱动协作",那么 AgentScope 则代表了另一种技术路径:<strong>工程化优先的多智能体平台</strong>。AgentScope 由阿里巴巴达摩院开发,专门为构建大规模、高可靠性的多智能体应用而设计。它不仅提供了直观易用的编程接口,更重要的是内置了分布式部署、容错恢复、可观测性等企业级特性,使其特别适合构建需要长期稳定运行的生产环境应用。
+
+### 6.3.1 AgentScope 的设计
+
+与 AutoGen 相比,AgentScope 的核心差异在于其<strong>消息驱动的架构设计</strong>和<strong>工业级的工程实践</strong>。如果说 AutoGen 更像是一个灵活的"对话工作室",那么 AgentScope 就是一个完整的"智能体操作系统",为开发者提供了从开发、测试到部署的全生命周期支持。与许多框架采用的继承式设计不同,AgentScope 选择了<strong>组合式架构</strong>和<strong>消息驱动模式</strong>。这种设计不仅增强了系统的模块化程度,也为其出色的并发性能和分布式能力奠定了基础。
+
+(1)分层架构体系
+
+如图6.2所示,AgentScope 采用了清晰的分层模块化设计,从底层的基础组件到上层的应用编排,形成了一个完整的智能体开发生态。
+
+<div align="center">
+  <img src="https://raw.githubusercontent.com/datawhalechina/Hello-Agents/main/docs/images/6-figures/03.png" alt="" width="90%"/>
+  <p>图 6.2 AgentScope架构图</p>
+</div>
+
+在这个架构中,最底层是<strong>基础组件层 (Foundational Components)</strong>,它为整个框架提供了核心的构建块。`Message` 组件定义了统一的消息格式,支持从简单的文本交互到复杂的多模态内容;`Memory` 组件提供了短期和长期记忆管理;`Model API` 层抽象了对不同大语言模型的调用;而 `Tool` 组件则封装了智能体与外部世界交互的能力。
+
+在基础组件之上,<strong>智能体基础设施层 (Agent-level Infrastructure)</strong> 提供了更高级的抽象。这一层不仅包含了各种预构建的智能体(如浏览器使用智能体、深度研究智能体),还实现了经典的 ReAct 范式,支持智能体钩子、并行工具调用、状态管理等高级特性。特别值得注意的是,这一层原生支持<strong>异步执行与实时控制</strong>,这是 AgentScope 相比其他框架的一个重要优势。
+
+<strong>多智能体协作层 (Multi-Agent Cooperation)</strong> 是 AgentScope 的核心创新所在。`MsgHub` 作为消息中心,负责智能体间的消息路由和状态管理;而 `Pipeline` 系统则提供了灵活的工作流编排能力,支持顺序、并发等多种执行模式。这种设计使得开发者可以轻松构建复杂的多智能体协作场景。
+
+最上层的<strong>开发与部署层 (Deployment & Devvelopment)</strong>则体现了 AgentScope 对工程化的重视。`AgentScope Runtime` 提供了生产级的运行时环境,而 `AgentScope Studio` 则为开发者提供了完整的可视化开发工具链。
+
+(2)消息驱动
+
+AgentScope 的核心创新在于其<strong>消息驱动架构</strong>。在这个架构中,所有的智能体交互都被抽象为<strong>消息</strong>的发送和接收,而不是传统的函数调用。
+
+```python
+from agentscope.message import Msg
+
+# 消息的标准结构
+message = Msg(
+    name="Alice",           # 发送者名称
+    content="Hello, Bob!",  # 消息内容
+    role="user",           # 角色类型
+    metadata={             # 元数据信息
+        "timestamp": "2024-01-15T10:30:00Z",
+        "message_type": "text",
+        "priority": "normal"
+    }
+)
+```
+
+将消息作为交互的基础单元,带来了几个关键优势:
+
+- <strong>异步解耦</strong>: 消息的发送方和接收方在时间上解耦,无需相互等待,天然支持高并发场景。
+- <strong>位置透明</strong>: 智能体无需关心另一个智能体是在本地进程还是在远程服务器上,消息系统会自动处理路由。
+- <strong>可观测性</strong>: 每一条消息都可以被记录、追踪和分析,极大地简化了复杂系统的调试与监控。
+- <strong>可靠性</strong>: 消息可以被持久化存储和重试,即使系统出现故障,也能保证交互的最终一致性,提升了系统的容错能力。
+
+(3)智能体生命周期管理
+
+在 AgentScope 中,每个智能体都有明确的生命周期(初始化、运行、暂停、销毁等),并基于一个统一的基类 `AgentBase` 来实现。开发者通常只需要关注其核心的 `reply` 方法。
+
+```python
+from agentscope.agents import AgentBase
+
+class CustomAgent(AgentBase):
+    def __init__(self, name: str, **kwargs):
+        super().__init__(name=name, **kwargs)
+        # 智能体初始化逻辑
+    
+    def reply(self, x: Msg) -> Msg:
+        # 智能体的核心响应逻辑
+        response = self.model(x.content)
+        return Msg(name=self.name, content=response, role="assistant")
+    
+    def observe(self, x: Msg) -> None:
+        # 智能体的观察逻辑(可选)
+        self.memory.add(x)
+```
+
+这种设计模式分离了智能体的内部逻辑与外部通信,开发者只需在 `reply` 方法中定义智能体“思考和回应”的方式即可。
+
+(4)消息传递机制
+
+AgentScope 内置了一个<strong>消息中心 (MsgHub)</strong>,它是整个消息驱动架构的中枢。MsgHub 不仅负责消息的路由和分发,还集成了持久化和分布式通信等高级功能,它有以下这些特点。
+
+- <strong>灵活的消息路由</strong>: 支持点对点、广播、组播等多种通信模式,可以构建灵活复杂的交互网络。
+- <strong>消息持久化</strong>: 能够将所有消息自动保存到数据库(如 SQLite, MongoDB),确保了长期运行任务的状态可以被恢复。
+- <strong>原生分布式支持</strong>: 这是 AgentScope 的标志性特性。智能体可以被部署在不同的进程或服务器上,`MsgHub` 会通过 RPC(远程过程调用)自动处理跨节点的通信,对开发者完全透明。
+
+这些由底层架构提供的工程化能力,使得 AgentScope 在处理需要高并发、高可靠性的复杂应用场景时,比传统的对话驱动框架更具优势。当然,这也要求开发者理解并适应消息驱动的异步编程范式。
+
+在下一节中,我们将通过一个具体的实战案例,三国狼人杀游戏,来深入体验 AgentScope 框架的能力,特别是其在处理并发交互方面的优势。
+
+### 6.3.2 三国狼人杀游戏
+
+为了深入理解 AgentScope 的消息驱动架构和多智能体协作能力,我们将构建一个融合了中国古典文化元素的"三国狼人杀"游戏。这个案例不仅展示了 AgentScope 在处理复杂多智能体交互方面的优势,更重要的是,它演示了如何在一个需要<strong>实时协作</strong>、<strong>角色扮演</strong>和<strong>策略博弈</strong>的场景中,充分发挥消息驱动架构的威力。与传统狼人杀不同,我们的"三国狼人杀"将刘备、关羽、诸葛亮等经典角色引入游戏,每个智能体不仅要完成狼人杀的基本任务(如狼人击杀、预言家查验、村民推理),还要体现出对应三国人物的性格特点和行为模式。这种设计让我们能够观察到 AgentScope 在处理<strong>多层次角色建模</strong>方面的表现。
+
+(1)架构设计与核心组件
+
+本案例的系统设计遵循了分层解耦的原则,将游戏逻辑划分为三个独立的层次,每个层次都映射了 AgentScope 的一个或多个核心组件:
+
+- <strong>游戏控制层 (Game Control Layer)</strong>:由一个 `ThreeKingdomsWerewolfGame` 类作为游戏的主控制器,负责维护全局状态(如玩家存活列表、当前游戏阶段)、推进游戏流程(调用夜晚阶段、白天阶段)以及裁定胜负。
+- <strong>智能体交互层 (Agent Interaction Layer)</strong>:完全由 `MsgHub` 驱动。所有智能体间的通信,无论是狼人间的秘密协商,还是白天的公开辩论,都通过消息中心进行路由和分发。
+- <strong>角色建模层 (Role Modeling Layer)</strong>:每个玩家都是一个基于 `DialogAgent` 的实例。我们通过精心设计的系统提示词,为每个智能体注入了“游戏角色”和“三国人格”的双重身份。
+
+(2)消息驱动的游戏流程
+
+本案例最核心的设计是以<strong>消息驱动</strong>代替<strong>状态机</strong>来管理游戏流程。在传统实现中,游戏阶段的转换通常由一个中心化的状态机(State Machine)控制。而在 AgentScope 的范式下,游戏流程被自然地建模为一系列定义好的消息交互模式。
+
+例如,狼人阶段的实现,并非一个简单的函数调用,而是通过 `MsgHub` 动态创建一个临时的、仅包含狼人玩家的私密通信频道:
+
+```python
+async def werewolf_phase(self, round_num: int):
+    """狼人阶段 - 展示消息驱动的协作模式"""
+    if not self.werewolves:
+        return None
+        
+    # 通过消息中心建立狼人专属通信频道
+    async with MsgHub(
+        self.werewolves,
+        enable_auto_broadcast=True,
+        announcement=await self.moderator.announce(
+            f"狼人们,请讨论今晚的击杀目标。存活玩家:{format_player_list(self.alive_players)}"
+        ),
+    ) as werewolves_hub:
+        # 讨论阶段:狼人通过消息交换策略
+        for _ in range(MAX_DISCUSSION_ROUND):
+            for wolf in self.werewolves:
+                await wolf(structured_model=DiscussionModelCN)
+        
+        # 投票阶段:收集并统计狼人的击杀决策
+        werewolves_hub.set_auto_broadcast(False)
+        kill_votes = await fanout_pipeline(
+            self.werewolves,
+            msg=await self.moderator.announce("请选择击杀目标"),
+            structured_model=WerewolfKillModelCN,
+            enable_gather=False,
+        )
+```
+
+这种设计的优势在于,游戏逻辑被清晰地表达为“在特定上下文中,以何种模式进行消息交换”,而不是一连串僵硬的状态转换。白天讨论(全员广播)、预言家查验(点对点请求)等阶段也都遵循同样的设计范式。
+
+(3)用结构化输出约束游戏规则
+
+狼人杀游戏的一个关键挑战是如何确保智能体的行为符合游戏规则。AgentScope 的<strong>结构化输出机制</strong>为这个问题提供了解决方案。我们为不同的游戏行为定义了严格的数据模型:
+
+```python
+class DiscussionModelCN(BaseModel):
+    """讨论阶段的输出格式"""
+    reach_agreement: bool = Field(
+        description="是否已达成一致意见",
+        default=False
+    )
+    confidence_level: int = Field(
+        description="对当前推理的信心程度(1-10)",
+        ge=1, le=10,
+        default=5
+    )
+    key_evidence: Optional[str] = Field(
+        description="支持你观点的关键证据",
+        default=None
+    )
+
+class WitchActionModelCN(BaseModel):
+    """女巫行动的输出格式"""
+    use_antidote: bool = Field(description="是否使用解药")
+    use_poison: bool = Field(description="是否使用毒药")
+    target_name: Optional[str] = Field(description="毒药目标玩家姓名")
+```
+
+通过这种方式,我们不仅确保了智能体输出的<strong>格式一致性</strong>,更重要的是实现了<strong>游戏规则的自动化约束</strong>。例如,女巫智能体无法同时对同一目标使用解药和毒药,预言家每晚只能查验一名玩家,这些约束都通过数据模型的字段定义和验证逻辑自动执行。
+
+(4)角色建模的双重挑战
+
+在这个案例中,最有趣的技术挑战是如何让智能体同时扮演好两个层面的角色:<strong>游戏功能角色</strong>(狼人、预言家等)和<strong>文化人格角色</strong>(刘备、曹操等)。我们通过提示词工程来解决这个问题:
+
+```python
+def get_role_prompt(role: str, character: str) -> str:
+    """获取角色提示词 - 融合游戏规则与人物性格"""
+    base_prompt = f"""你是{character},在这场三国狼人杀游戏中扮演{role}。
+
+重要规则:
+1. 你只能通过对话和推理参与游戏
+2. 不要尝试调用任何外部工具或函数
+3. 严格按照要求的JSON格式回复
+
+角色特点:
+"""
+    
+    if role == "狼人":
+        return base_prompt + f"""
+- 你是狼人阵营,目标是消灭所有好人
+- 夜晚可以与其他狼人协商击杀目标
+- 白天要隐藏身份,误导好人
+- 以{character}的性格说话和行动
+"""
+```
+
+这种设计让我们观察到了一个有趣的现象:不同的三国人物在扮演相同游戏角色时,会表现出截然不同的策略和话语风格。例如,扮演狼人的"曹操"可能会表现得更加狡猾和善于伪装,而扮演狼人的"张飞"则可能显得更加直接和冲动。
+
+(5)并发处理与容错机制
+
+AgentScope 的异步架构在这个多智能体游戏中发挥了重要作用。游戏中经常出现需要<strong>同时收集多个智能体决策</strong>的场景,比如投票阶段:
+
+```python
+# 并行收集所有玩家的投票决策
+vote_msgs = await fanout_pipeline(
+    self.alive_players,
+    await self.moderator.announce("请投票选择要淘汰的玩家"),
+    structured_model=get_vote_model_cn(self.alive_players),
+    enable_gather=False,
+)
+```
+
+`fanout_pipeline` 允许我们并行地向所有智能体发送相同的消息,并异步收集它们的响应。这不仅提高了游戏的执行效率,更重要的是模拟了真实狼人杀游戏中"同时投票"的场景。同时,我们在关键环节加入了容错处理:
+
+```python
+try:
+    response = await wolf(
+        "请分析当前局势并表达你的观点。",
+        structured_model=DiscussionModelCN
+    )
+except Exception as e:
+    print(f"⚠️ {wolf.name} 讨论时出错: {e}")
+    # 创建默认响应,确保游戏继续进行
+    default_response = DiscussionModelCN(
+        reach_agreement=False,
+        confidence_level=5,
+        key_evidence="暂时无法分析"
+    )
+```
+
+这种设计确保了即使某个智能体出现异常,整个游戏流程也能继续进行。
+
+(6)案例输出与总结
+
+为了更直观地感受 AgentScope 的运行机制,以下是一段截取自游戏夜晚阶段的真实运行日志,展示了扮演“孙权”和“周瑜”的两个狼人智能体进行秘密协商并执行击杀的过程。
+
+```
+🎮 欢迎来到三国狼人杀!
+
+=== 游戏初始化 ===
+游戏主持人: 📢 【孙权】你在这场三国狼人杀中扮演狼人,你的角色是孙权。夜晚可以击杀一名玩家
+游戏主持人: 📢 【周瑜】你在这场三国狼人杀中扮演狼人,你的角色是周瑜。夜晚可以击杀一名玩家
+...
+
+游戏主持人: 📢 三国狼人杀游戏开始!参与者:孙权、周瑜、曹操、张飞、司马懿、赵云
+✅ 游戏设置完成,共6名玩家
+
+=== 第1轮游戏 ===
+🌙 第1夜降临,天黑请闭眼...
+
+【狼人阶段】
+游戏主持人: 📢 🐺 狼人请睁眼,选择今晚要击杀的目标...
+游戏主持人: 📢 狼人们,请讨论今晚的击杀目标。存活玩家:孙权、周瑜、曹操、张飞、司马懿、赵云
+
+孙权: 今晚我们应该除掉周瑜,此人智谋过人,对我们威胁很大。
+周瑜: 孙权,你言之有理。但周瑜虽智,却未必是今晚的最大威胁。曹操势力庞大,若不尽早除去,恐对我们不利。
+孙权: 曹操的确是个威胁,但周瑜若活着,他能够识破我们的计谋。不如先解决眼前的隐患。
+周瑜: 孙权,你的顾虑不无道理。但曹操若与我们为敌,他可以联合其他势力对我们构成更大的威胁。
+孙权: 你说的也有道理,曹操的联合确实麻烦。那我们就先对付曹操吧。
+周瑜: 很好,孙权。曹操才是我们今晚首要的目标。
+
+游戏主持人: 📢 请选择击杀目标
+孙权: 我同意,曹操必须被除掉。
+周瑜: 我同意,曹操是我们今晚要解决的目标。
+
+【预言家阶段】
+游戏主持人: 📢 🔮 预言家请睁眼,选择要查验的玩家...
+曹操: 我要查验孙权。
+游戏主持人: 📢 查验结果:孙权是狼人
+
+【女巫阶段】
+游戏主持人: 📢 🧙‍♀️ 女巫请睁眼...
+游戏主持人: 📢 今晚曹操被狼人击杀
+张飞: 我昨晚使用了解药救了曹操,现在解药已经用掉了。
+游戏主持人: 📢 你使用解药救了曹操
+
+游戏主持人: 📢 昨夜平安无事,无人死亡。
+
+【白天讨论阶段】
+游戏主持人: 📢 ☀️ 第1天天亮了,请大家睁眼...
+游戏主持人: 📢 现在开始自由讨论。存活玩家:孙权、周瑜、曹操、张飞、司马懿、赵云
+
+孙权: 诸位,曹操势力庞大,对我们都是潜在的威胁。今晚我建议我们集中力量对付他。
+周瑜: 孙权所言极是,曹操不仅自身强大,还可能与其他玩家结盟,对我们构成更大的威胁。
+曹操: 我昨晚查验了孙权,本以为他是好人,但游戏主持人给出的结果却是狼人。这说明有狼人在说谎。
+张飞: 我昨晚确实救了曹操,说明他是被狼人袭击的。但曹操查验孙权的结果令人怀疑。
+司马懿: 曹操的查验结果和张飞的救人行动似乎存在矛盾,我们需要更多的信息来判断谁是狼人。
+赵云: 情况确实复杂,我们需要仔细分析各方的发言。
+
+【投票阶段】
+游戏主持人: 📢 请投票选择要淘汰的玩家
+
+孙权: 曹操的威胁依然很大,我坚持认为应该投票给他。
+周瑜: 基于昨晚的情况,我认为我们应该先投票给曹操,他的威胁最大。
+曹操: 我选择投票给孙权。根据游戏主持人的反馈,孙权确实是狼人。
+张飞: 我坚持昨晚救了曹操的事实,但孙权被查出是狼人这一点让我感到困惑。
+司马懿: 我们需要更多的信息来判断谁是狼人。
+
+[游戏继续...]
+```
+
+### 6.3.3 AgentScope 的优势与局限性分析
+
+通过这个"三国狼人杀"案例,我们深度体验了 AgentScope 框架的核心优势。该框架以其消息驱动的架构为核心,将复杂的游戏流程优雅地映射为一系列并发、异步的消息传递事件,从而避免了传统状态机的僵硬与复杂。结合其强大的结构化输出能力,我们将游戏规则直接转化为代码层面的约束,极大地提升了系统的稳定性和可预测性。这种设计范式不仅在性能上展现了其原生并发的优势,更在容错处理上保证了即使单个智能体出现异常,整体流程也能稳健运行。
+
+然而,AgentScope 的工程化优势也带来了一定的复杂性成本。其消息驱动架构虽然强大,但对开发者的技术要求较高,需要理解异步编程、分布式通信等概念。对于简单的多智能体对话场景,这种架构可能显得过于复杂,存在"过度工程化"的风险。此外,作为相对较新的框架,其生态系统和社区资源还有待进一步完善。因此,AgentScope 更适合需要构建大规模、高可靠性的生产级多智能体系统,而对于快速原型开发或简单应用场景,选择更轻量级的框架可能更为合适。
+
+
+
+## 6.4 框架三:CAMEL
+
+与 AutoGen 和 AgentScope 这样功能全面的框架不同,CAMEL最初的核心目标是探索如何在最少的人类干预下,让两个智能体通过“角色扮演”自主协作解决复杂任务。
+
+### 6.4.1 CAMEL 的自主协作
+
+CAMEL 实现自主协作的基石是两大核心概念:<strong>角色扮演 (Role-Playing)</strong> 和 <strong>引导性提示 (Inception Prompting)</strong>。
+
+(1)角色扮演
+
+在 CAMEL 最初的设计中,一个任务通常由两个智能体协作完成。这两个智能体被赋予了互补的、明确定义的“角色”。一个扮演<strong>“AI 用户” (AI User)</strong>,负责提出需求、下达指令和构思任务步骤;另一个则扮演<strong>“AI 助理” (AI Assistant)</strong>,负责根据指令执行具体操作和提供解决方案。
+
+例如,在一个“开发股票交易策略分析工具”的任务中:
+
+- <strong>AI 用户</strong> 的角色可能是一位“资深股票交易员”。它懂市场、懂策略,但不懂编程。
+- <strong>AI 助理</strong> 的角色则是一位“优秀的 Python 程序员”。它精通编程,但对股票交易一无所知。
+
+通过这种设定,任务的解决过程就被自然地转化为一场两位“跨领域专家”之间的对话。交易员提出专业需求,程序员将其转化为代码实现,两者协作完成任何一方都无法独立完成的复杂任务。
+
+(2)引导性提示
+
+仅仅设定角色还不够,如何确保两个 AI 在没有人类持续监督的情况下,能始终“待在自己的角色里”,并且高效地朝着共同目标前进呢?这就是 CAMEL 最核心的技术,引导性提示发挥作用的地方。“引导性提示”是在对话开始前,分别注入给两个智能体的一段精心设计的、结构化的初始指令(System Prompt)。这段指令就像是为智能体植入的“行动纲领”,它通常包含以下几个关键部分:
+
+- <strong>明确自身角色</strong>:例如,“你是一位资深的股票交易员...”
+- <strong>告知协作者角色</strong>:例如,“你正在与一位优秀的 Python 程序员合作...”
+- <strong>定义共同目标</strong>:例如,“你们的共同目标是开发一个股票交易策略分析工具。”
+- <strong>设定行为约束和沟通协议</strong>:这是最关键的一环。例如,指令会要求 AI 用户“一次只提出一个清晰、具体的步骤”,并要求 AI 助理“在完成上一步之前不要追问更多细节”,同时规定双方需在回复的末尾使用特定标志(如 `<SOLUTION>`)来标识任务的完成。
+
+这些约束条件确保了对话不会偏离主题、不会陷入无效循环,而是以一种高度结构化、任务驱动的方式向前推进,如图6.3所示。
+
+<div align="center">
+  <img src="https://raw.githubusercontent.com/datawhalechina/Hello-Agents/main/docs/images/6-figures/04.png" alt="" width="90%"/>
+  <p>图 6.3 CAMEL创建股票机器人交易</p>
+</div>
+
+在下一节,我们将通过一个具体的实例来体验这一过程。
+
+### 6.4.2 AI科普电子书
+
+为了理解 CAMEL 框架的角色扮演能力,我们将构建一个具有实际价值的协作案例:让一位 AI 心理学家与一位 AI 作者合作,共同创作一本关于"拖延症心理学"的短篇电子书。这个案例体现了 CAMEL 的核心优势,让两个智能体在各自专业领域发挥所长,协作完成单个智能体难以胜任的复杂创作任务。
+
+(1)任务设定
+
+<strong>场景设定</strong>:创作一本面向普通读者的拖延症心理学科普电子书,要求既有科学严谨性,又具备良好的可读性。
+
+<strong>智能体角色</strong>:
+
+- <strong>心理学家(Psychologist)</strong>:具备深厚的心理学理论基础,熟悉认知行为科学、神经科学等相关领域,能够提供专业的学术见解和实证研究支持
+- <strong>作家(Writer)</strong>:拥有优秀的写作技巧和叙述能力,善于将复杂的学术概念转化为生动易懂的文字,注重读者体验和内容的可读性
+
+(2)定义协作任务
+
+首先,我们需要明确两位 AI 专家的共同目标。我们通过一个内容详实的字符串 `task_prompt` 来定义这个任务。
+
+```python
+from colorama import Fore
+from camel.societies import RolePlaying
+from camel.utils import print_text_animated
+
+# 定义协作任务
+task_prompt = """
+创作一本关于"拖延症心理学"的短篇电子书,目标读者是对心理学感兴趣的普通大众。
+要求:
+1. 内容科学严谨,基于实证研究
+2. 语言通俗易懂,避免过多专业术语
+3. 包含实用的改善建议和案例分析
+4. 篇幅控制在8000-10000字
+5. 结构清晰,包含引言、核心章节和总结
+"""
+
+print(Fore.YELLOW + f"协作任务:\n{task_prompt}\n")
+```
+
+`task_prompt` 是整个协作的“任务说明书”。它不仅是我们要完成的目标,也将在幕后被 CAMEL 用来生成“引导性提示”,确保两位智能体的对话始终围绕这个核心目标展开。
+
+(3)初始化角色扮演“社会”
+
+接下来,我们创建 `RolePlaying` 会话实例。这是 CAMEL 的核心操作,它根据我们提供的角色和任务,快速构建一个双智能体协作“社会”。
+
+```python
+# 初始化角色扮演会话
+# AI 作家作为 "user",负责提出写作结构和要求
+# AI 心理学家作为 "assistant",负责提供专业知识和内容
+role_play_session = RolePlaying(
+    assistant_role_name="心理学家",
+    user_role_name="作家",
+    task_prompt=task_prompt,
+    with_task_specify=False, # 在本例中,我们直接使用给定的task_prompt
+)
+
+print(Fore.CYAN + f"具体任务描述:\n{role_play_session.task_prompt}\n")
+```
+
+`RolePlaying` 是 CAMEL 提供的高级 API,它封装了复杂的提示工程。我们只需传入两个角色的名称和任务即可。在 CAMEL 的设计中,`user` 角色是对话的“推动者”和“需求方”,而 `assistant` 角色是“执行者”和“方案提供方”。因此,我们将负责规划结构的“作家”分配给 `user_role_name`,将负责提供专业知识的“心理学家”分配给 `assistant_role_name`。
+
+(4)启动并运行自动化对话
+
+最后,我们编写一个循环来驱动整个对话过程,让两位 AI 专家开始它们的自动化协作。
+
+```python
+# 开始协作对话
+chat_turn_limit, n = 30, 0
+# 调用 init_chat() 来获得由 AI 生成的初始对话消息
+input_msg = role_play_session.init_chat()
+
+while n < chat_turn_limit:
+    n += 1
+    # step() 方法驱动一轮完整的对话,AI 用户和 AI 助理各发言一次
+    assistant_response, user_response = role_play_session.step(input_msg)
+    
+    # 检查是否有消息返回,防止对话提前终止
+    if assistant_response.msg is None or user_response.msg is None:
+        break
+    
+    print_text_animated(Fore.BLUE + f"作家 (AI User):\n\n{user_response.msg.content}\n")
+    print_text_animated(Fore.GREEN + f"心理学家 (AI Assistant):\n\n{assistant_response.msg.content}\n")
+    
+    # 检查任务完成标志
+    if "<CAMEL_TASK_DONE>" in user_response.msg.content or "<CAMEL_TASK_DONE>" in assistant_response.msg.content:
+        print(Fore.MAGENTA + "✅ 电子书创作完成!")
+        break
+    
+    # 将助理的回复作为下一轮对话的输入
+    input_msg = assistant_response.msg
+
+print(Fore.YELLOW + f"总共进行了 {n} 轮协作对话")
+```
+
+这段 `while` 循环是自动化协作的核心。对话由 `init_chat()` 方法基于任务和角色自动开启,无需人工编写开场白。循环的每一步都通过调用 `step()` 来驱动一轮完整的交互(作家提需求、心理学家给内容),并将上一轮心理学家的输出作为下一轮的输入,形成环-环相扣的创作链。整个过程将持续进行,直到达到预设的对话轮次上限,或任一智能体输出任务完成标志 `<CAMEL_TASK_DONE>` 后自动终止。
+
+(5)协作流程展示
+
+当执行上述代码后,我们并非只是得到一长串单调的问答,而是能够观察到一个高度结构化的、如同人类专家团队般的协作流程在自动进行。整个创作过程自然地分为几个阶段:
+
+<strong>第一阶段 (约 1-5 轮): 框架搭建与目标对齐</strong> 在对话的初期,“作家”智能体首先会扮演起主导者的角色,提出对电子书整体结构和章节安排的初步设想。随后,“心理学家”会从其专业角度对这个框架进行审视和补充,确保核心的学术模块(如理论基础、关键概念等)没有遗漏,从而在协作开始之初就对最终产出物达成共识。
+
+<strong>第二阶段 (约 6-20 轮): 核心内容生成与知识转译</strong> 这是最高效的内容创作阶段。协作模式会变为一种稳定的“请求-响应”循环:
+
+- <strong>心理学家</strong>:负责提供“硬核”的专业知识,如对“时间折扣理论”、“执行功能缺陷”等核心概念的科学解释,并引用相关的实验研究来支撑观点。
+- <strong>作家</strong>:则发挥其“翻译官”的作用,将这些严谨但可能晦涩的学术概念,转化为生动、形象的比喻和贴近生活的案例。例如,它可能会将“大脑中的‘现在偏见’”这个概念,比作“一个只顾眼前糖果、不顾长远健康的任性孩子”。
+
+<strong>第三阶段 (约 21-25 轮): 迭代优化与质量保证</strong> 当书籍的主体内容完成后,对话的重心会转移到对已有文本的打磨和完善上。此时,两位智能体的角色会发生微妙的变化:
+
+- <strong>作家</strong>:更侧重于审视文章的整体流畅性、逻辑衔接和语言风格,从“读者体验”出发提出修改建议。
+- <strong>心理学家</strong>:则再次扮演“事实核查员”,确保在转译和润色的过程中,核心知识的科学准确性没有丢失,并为某些观点补充更有力的实证研究支持。
+
+<strong>第四阶段 (收尾): 总结与升华</strong> 在最后的几轮对话中,双方会协作完成实用建议的总结和全书的回顾,确保电子书有一个清晰、有力的结尾,为读者留下深刻印象并提供实际价值。
+
+```
+协作任务:
+创作一本关于"拖延症心理学"的短篇电子书,目标读者是对心理学感兴趣的普通大众。
+要求:
+1. 内容科学严谨,基于实证研究
+2. 语言通俗易懂,避免过多专业术语
+3. 包含实用的改善建议和案例分析
+4. 篇幅控制在8000-10000字
+5. 结构清晰,包含引言、核心章节和总结
+
+具体任务描述:
+为普通大众撰写8000–10000字短篇电子书《拖延症心理学》:实证为本、通俗易懂。结构:引言、成因(认知/情绪/奖励)、动机与决策、习惯形成与干预、实
+用策略与练习、三则案例分析、总结与资源。每章含研究引用与可操作步骤。
+
+作家:
+Instruction: 请为电子书的“引言”章节撰写一段400–600字的中文草稿...
+Input: None
+
+心理学家:
+Solution:
+草稿:拖延,是指明知应当完成某项任务却反复推迟或回避的行为与内在倾向。它既可以是偶发的时间管理问题...
+
+Next request.
+
+作家:
+Instruction: 请把下面的引言草稿修订为一段450–550字的中文文本...
+Input: 草稿:拖延,是指明知应当完成某项任务却反复推迟或回避的行为...
+.....
+```
+
+### 6.4.3 CAMEL 的优势与局限性分析
+
+通过前面的电子书创作案例,我们深度体验了 CAMEL 框架独特的角色扮演范式。现在让我们客观地分析这种设计理念的优势与局限性,以便在实际项目中做出明智的技术选型。
+
+(1)优势
+
+CAMEL 最大的优势在于其"轻架构、重提示"的设计哲学。相比 AutoGen 的复杂对话管理和 AgentScope 的分布式架构,CAMEL 通过精心设计的初始提示就能实现高质量的智能体协作。这种自然涌现的协作行为,往往比硬编码的工作流更加灵活和高效。
+
+值得注意的是,CAMEL 框架正在经历快速的发展和演进。从其 [GitHub 仓库](https://github.com/camel-ai/camel) 可以看到,CAMEL 已经远不止是一个简单的双智能体协作框架,目前已经具备:
+
+- <strong>多模态能力</strong>:支持文本、图像、音频等多种模态的智能体协作
+- <strong>工具集成</strong>:内置了丰富的工具库,包括搜索、计算、代码执行等
+- <strong>模型适配</strong>:支持 OpenAI、Anthropic、Google、开源模型等多种 LLM 后端
+- <strong>生态联动</strong>:与 LangChain、CrewAI、AutoGen 等主流框架实现了互操作性
+
+(2)主要局限性
+
+1. 对提示工程的高度依赖
+
+CAMEL 的成功很大程度上取决于初始提示的质量。这带来了几个挑战:
+
+- <strong>提示设计门槛</strong>:需要深入理解目标领域和 LLM 的行为特性
+- <strong>调试复杂性</strong>:当协作效果不佳时,很难定位是角色定义、任务描述还是交互规则的问题
+- <strong>一致性挑战</strong>:不同的 LLM 对相同提示的理解可能存在差异
+
+2. 协作规模的限制
+
+虽然 CAMEL 在双智能体协作上表现出色,但在处理大规模多智能体场景时面临挑战:
+
+- <strong>对话管理</strong>:缺乏像 AutoGen 那样的复杂对话路由机制
+- <strong>状态同步</strong>:没有 AgentScope 那样的分布式状态管理能力
+- <strong>冲突解决</strong>:当多个智能体意见分歧时,缺乏有效的仲裁机制
+
+3. 任务适用性的边界
+
+CAMEL 特别适合需要深度协作和创造性思维的任务,但在某些场景下可能不是最优选择:
+
+- <strong>严格流程控制</strong>:对于需要精确步骤控制的任务,LangGraph 的图结构更合适
+- <strong>大规模并发</strong>:AgentScope 的消息驱动架构在高并发场景下更有优势
+- <strong>复杂决策树</strong>:AutoGen 的群聊模式在多方决策场景下更加灵活
+
+总的来说,CAMEL 代表了一种独特而优雅的多智能体协作范式。它通过"以人为本"的角色扮演设计,将复杂的系统工程问题转化为直观的人际协作模式。随着其生态系统的不断完善和功能的持续扩展,CAMEL 正在成为构建智能协作系统的重要选择之一。
+
+## 6.5 框架四:LangGraph
+
+### 6.5.1 LangGraph 的结构梳理
+
+LangGraph 作为 LangChain 生态系统的重要扩展,代表了智能体框架设计的一个全新方向。与前面介绍的基于“对话”的框架(如 AutoGen 和 CAMEL)不同,LangGraph 将智能体的执行流程建模为一种<strong>状态机(State Machine)</strong>,并将其表示为<strong>有向图(Directed Graph)</strong>。在这种范式中,图的<strong>节点(Nodes)</strong>代表一个具体的计算步骤(如调用 LLM、执行工具),而<strong>边(Edges)</strong>则定义了从一个节点到另一个节点的跳转逻辑。这种设计的革命性之处在于它天然支持循环,使得构建能够进行迭代、反思和自我修正的复杂智能体工作流变得前所未有的直观和简单。
+
+要理解 LangGraph,我们需要先掌握它的三个基本构成要素。
+
+<strong>首先,是全局状态(State)</strong>。整个图的执行过程都围绕一个共享的状态对象进行。这个状态通常被定义为一个 Python 的 `TypedDict`,它可以包含任何你需要追踪的信息,如对话历史、中间结果、迭代次数等。所有的节点都能读取和更新这个中心状态。
+
+```python
+from typing import TypedDict, List
+
+# 定义全局状态的数据结构
+class AgentState(TypedDict):
+    messages: List[str]      # 对话历史
+    current_task: str        # 当前任务
+    final_answer: str        # 最终答案
+    # ... 任何其他需要追踪的状态
+```
+
+<strong>其次,是节点(Nodes)</strong>。每个节点都是一个接收当前状态作为输入、并返回一个更新后的状态作为输出的 Python 函数。节点是执行具体工作的单元。
+
+```python
+# 定义一个“规划者”节点函数
+def planner_node(state: AgentState) -> AgentState:
+    """根据当前任务制定计划,并更新状态。"""
+    current_task = state["current_task"]
+    # ... 调用LLM生成计划 ...
+    plan = f"为任务 '{current_task}' 生成的计划..."
+    
+    # 将新消息追加到状态中
+    state["messages"].append(plan)
+    return state
+
+# 定义一个“执行者”节点函数
+def executor_node(state: AgentState) -> AgentState:
+    """执行最新计划,并更新状态。"""
+    latest_plan = state["messages"][-1]
+    # ... 执行计划并获得结果 ...
+    result = f"执行计划 '{latest_plan}' 的结果..."
+    
+    state["messages"].append(result)
+    return state
+```
+
+<strong>最后,是边(Edges)</strong>。边负责连接节点,定义工作流的方向。最简单的边是常规边,它指定了一个节点的输出总是流向另一个固定的节点。而 LangGraph 最强大的功能在于<strong>条件边(Conditional Edges)</strong>。它通过一个函数来判断当前的状态,然后动态地决定下一步应该跳转到哪个节点。这正是实现循环和复杂逻辑分支的关键。
+
+```python
+def should_continue(state: AgentState) -> str:
+    """条件函数:根据状态决定下一步路由。"""
+    # 假设如果消息少于3条,则需要继续规划
+    if len(state["messages"]) < 3:
+        # 返回的字符串需要与添加条件边时定义的键匹配
+        return "continue_to_planner"
+    else:
+        state["final_answer"] = state["messages"][-1]
+        return "end_workflow"
+```
+
+在定义了状态、节点和边之后,我们可以像搭积木一样将它们组装成一个可执行的工作流。
+
+```python
+from langgraph.graph import StateGraph, END
+
+# 初始化一个状态图,并绑定我们定义的状态结构
+workflow = StateGraph(AgentState)
+
+# 将节点函数添加到图中
+workflow.add_node("planner", planner_node)
+workflow.add_node("executor", executor_node)
+
+# 设置图的入口点
+workflow.set_entry_point("planner")
+
+# 添加常规边,连接 planner 和 executor
+workflow.add_edge("planner", "executor")
+
+# 添加条件边,实现动态路由
+workflow.add_conditional_edges(
+    # 起始节点
+    "executor",
+    # 判断函数
+    should_continue,
+    # 路由映射:将判断函数的返回值映射到目标节点
+    {
+        "continue_to_planner": "planner", # 如果返回"continue_to_planner",则跳回planner节点
+        "end_workflow": END               # 如果返回"end_workflow",则结束流程
+    }
+)
+
+# 编译图,生成可执行的应用
+app = workflow.compile()
+
+# 运行图
+inputs = {"current_task": "分析最近的AI行业新闻", "messages": []}
+for event in app.stream(inputs):
+    print(event)
+```
+
+### 6.5.2 三步问答助手
+在理解了 LangGraph 的核心概念之后,我们将通过一个实战案例来巩固所学。我们将构建一个简化的问答对话助手,它会遵循一个清晰、固定的三步流程来回答用户的问题:
+
+1. <strong>理解 (Understand)</strong>:首先,分析用户的查询意图。
+2. <strong>搜索 (Search)</strong>:然后,模拟搜索与意图相关的信息。
+3. <strong>回答 (Answer)</strong>:最后,基于意图和搜索到的信息,生成最终答案。
+
+这个案例将清晰地展示如何定义状态、创建节点以及将它们线性地连接成一个完整的工作流。我们将代码分解为四个核心步骤:定义状态、创建节点、构建图、以及运行应用。
+
+(1)定义全局状态
+
+首先,我们需要定义一个贯穿整个工作流的全局状态。<strong>这是一个共享的数据结构,它在图的每个节点之间传递,作为工作流的持久化上下文。</strong> 每个节点都可以读取该结构中的数据,并对其进行更新。
+
+```python
+from typing import TypedDict, Annotated
+from langgraph.graph.message import add_messages
+
+class SearchState(TypedDict):
+    messages: Annotated[list, add_messages]
+    user_query: str      # 经过LLM理解后的用户需求总结
+    search_query: str    # 优化后用于Tavily API的搜索查询
+    search_results: str  # Tavily搜索返回的结果
+    final_answer: str    # 最终生成的答案
+    step: str            # 标记当前步骤
+```
+
+我们创建了 `SearchState` 这个 `TypedDict`,为状态对象定义了一个清晰的数据模式(Schema)。一个关键的设计是同时包含了 `user_query` 和 `search_query` 字段。这允许智能体先将用户的自然语言提问,优化成更适合搜索引擎的精炼关键词,从而显著提升搜索结果的质量。
+
+(2)定义工作流节点
+
+定义好状态结构后,下一步是创建构成我们工作流的各个节点。在 LangGraph 中,每个节点都是一个执行具体任务的 Python 函数。这些函数接收当前的状态对象作为输入,并返回一个包含更新后字段的字典。
+
+在开始定义节点之前,我们先完成项目的初始化设置,包括加载环境变量和实例化大语言模型。
+
+```python
+import os
+from dotenv import load_dotenv
+from langchain_openai import ChatOpenAI
+from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
+from tavily import TavilyClient
+
+# 加载 .env 文件中的环境变量
+load_dotenv()
+
+# 初始化模型
+# 我们将使用这个 llm 实例来驱动所有节点的智能
+llm = ChatOpenAI(
+    model=os.getenv("LLM_MODEL_ID", "gpt-4o-mini"),
+    api_key=os.getenv("LLM_API_KEY"),
+    base_url=os.getenv("LLM_BASE_URL", "https://api.openai.com/v1"),
+    temperature=0.7
+)
+# 初始化Tavily客户端
+tavily_client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
+```
+
+现在,我们来逐一创建三个核心节点。
+
+(1) 理解与查询节点
+
+此节点是工作流的第一步,此节点的职责是理解用户意图,并为其生成一个最优化的搜索查询。
+
+```python
+def understand_query_node(state: SearchState) -> dict:
+    """步骤1:理解用户查询并生成搜索关键词"""
+    user_message = state["messages"][-1].content
+    
+    understand_prompt = f"""分析用户的查询:"{user_message}"
+请完成两个任务:
+1. 简洁总结用户想要了解什么
+2. 生成最适合搜索引擎的关键词(中英文均可,要精准)
+
+格式:
+理解:[用户需求总结]
+搜索词:[最佳搜索关键词]"""
+
+    response = llm.invoke([SystemMessage(content=understand_prompt)])
+    response_text = response.content
+    
+    # 解析LLM的输出,提取搜索关键词
+    search_query = user_message # 默认使用原始查询
+    if "搜索词:" in response_text:
+        search_query = response_text.split("搜索词:")[1].strip()
+    
+    return {
+        "user_query": response_text,
+        "search_query": search_query,
+        "step": "understood",
+        "messages": [AIMessage(content=f"我将为您搜索:{search_query}")]
+    }
+```
+
+该节点通过一个结构化的提示,要求 LLM 同时完成“意图理解”和“关键词生成”两个任务,并将解析出的专用搜索关键词更新到状态的 `search_query` 字段中,为下一步的精确搜索做好准备。
+
+(2)搜索节点
+
+该节点负责执行智能体的“工具使用”能力,它将调用 Tavily API 进行真实的互联网搜索,并具备基础的错误处理功能。
+
+```python
+def tavily_search_node(state: SearchState) -> dict:
+    """步骤2:使用Tavily API进行真实搜索"""
+    search_query = state["search_query"]
+    try:
+        print(f"🔍 正在搜索: {search_query}")
+        response = tavily_client.search(
+            query=search_query, search_depth="basic", max_results=5, include_answer=True
+        )
+        # ... (处理和格式化搜索结果) ...
+        search_results = ... # 格式化后的结果字符串
+        
+        return {
+            "search_results": search_results,
+            "step": "searched",
+            "messages": [AIMessage(content="✅ 搜索完成!正在整理答案...")]
+        }
+    except Exception as e:
+        # ... (处理错误) ...
+        return {
+            "search_results": f"搜索失败:{e}",
+            "step": "search_failed",
+            "messages": [AIMessage(content="❌ 搜索遇到问题...")]
+        }
+```
+
+此节点通过 `tavily_client.search` 发起真实的 API 调用。它被包裹在 `try...except` 块中,用于捕获可能的异常。如果搜索失败,它会更新 `step` 状态为 `"search_failed"`,这个状态将被下一个节点用来触发备用方案。
+
+(3)回答节点
+
+最后的回答节点能够根据上一步的搜索是否成功,来选择不同的回答策略,具备了一定的弹性。
+
+```python
+def generate_answer_node(state: SearchState) -> dict:
+    """步骤3:基于搜索结果生成最终答案"""
+    if state["step"] == "search_failed":
+        # 如果搜索失败,执行回退策略,基于LLM自身知识回答
+        fallback_prompt = f"搜索API暂时不可用,请基于您的知识回答用户的问题:\n用户问题:{state['user_query']}"
+        response = llm.invoke([SystemMessage(content=fallback_prompt)])
+    else:
+        # 搜索成功,基于搜索结果生成答案
+        answer_prompt = f"""基于以下搜索结果为用户提供完整、准确的答案:
+用户问题:{state['user_query']}
+搜索结果:\n{state['search_results']}
+请综合搜索结果,提供准确、有用的回答..."""
+        response = llm.invoke([SystemMessage(content=answer_prompt)])
+    
+    return {
+        "final_answer": response.content,
+        "step": "completed",
+        "messages": [AIMessage(content=response.content)]
+    }
+```
+
+该节点通过检查 `state["step"]` 的值来执行条件逻辑。如果搜索失败,它会利用 LLM 的内部知识回答并告知用户情况。如果搜索成功,它则会使用包含实时搜索结果的提示,来生成一个有时效性且有据可依的回答。
+
+(4)构建图
+
+我们将所有节点连接起来。
+
+```python
+from langgraph.graph import StateGraph, START, END
+from langgraph.checkpoint.memory import InMemorySaver
+
+def create_search_assistant():
+    workflow = StateGraph(SearchState)
+    
+    # 添加节点
+    workflow.add_node("understand", understand_query_node)
+    workflow.add_node("search", tavily_search_node)
+    workflow.add_node("answer", generate_answer_node)
+    
+    # 设置线性流程
+    workflow.add_edge(START, "understand")
+    workflow.add_edge("understand", "search")
+    workflow.add_edge("search", "answer")
+    workflow.add_edge("answer", END)
+    
+    # 编译图
+    memory = InMemorySaver()
+    app = workflow.compile(checkpointer=memory)
+    return app
+```
+
+(5)运行案例展示 
+
+运行此脚本后,您可以提出一些需要实时信息的问题,例如我们第一章中的案例:`明天我要去北京,天气怎么样?有合适的景点吗`
+
+您会看到终端清晰地展示出智能体的“思考”过程:
+
+```
+🔍 智能搜索助手启动!
+我会使用Tavily API为您搜索最新、最准确的信息
+支持各种问题:新闻、技术、知识问答等
+(输入 'quit' 退出)
+
+🤔 您想了解什么: 明天我要去北京,天气怎么样?有合适的景点吗
+
+============================================================
+🧠 理解阶段: 我理解您的需求:理解:用户想了解明天北京的天气情况以及合适的景点推荐。  
+搜索词:北京 明天 天气 景点推荐 Beijing weather tomorrow attractions
+🔍 正在搜索: 北京 明天 天气 景点推荐 Beijing weather tomorrow attractions
+🔍 搜索阶段: ✅ 搜索完成!找到了相关信息,正在为您整理答案...
+
+💡 最终回答:
+明天(2025年9月17日)北京的天气预报显示,预计将是多云,气温范围在17°C(62°F)到25°C(77°F)之间。这种温和的天气非常适合户外活动。
+
+### 合适的景点推荐:
+1. **长城**:作为中国最著名的历史遗址之一,长城是必游之地。你可以选择八达岭或慕田峪这些较为受欢迎的段落进行游览。
+
+2. **故宫**:故宫是明清两代的皇宫,拥有丰富的历史和文化,适合对中国历史感兴趣的游客。
+
+3. **天安门广场**:这是中国的象征之一,广场上有许多重要的建筑和纪念碑,适合拍照留念。
+
+4. **颐和园**:一个非常美丽的皇家园林,适合漫步和欣赏自然风光,尤其是湖泊和古建筑。
+
+5. **798艺术区**:如果你对现代艺术感兴趣,798艺术区是一个集艺术、文化和创意于一体的地方,适合探索和拍摄。
+
+### 小贴士:
+- 由于明天天气良好,建议提前规划出行路线,并准备一些水和小吃,以便在游览时保持充足的体力。
+- 由于天气变化可能会影响游览体验,建议查看实时天气更新。
+
+希望这些信息能帮助你安排一个愉快的北京之旅!如果你需要更多关于景点的信息或者旅行建议,欢迎随时询问。
+
+============================================================
+
+🤔 您想了解什么:
+```
+
+并且他是一个可以持续交互的助手,你也可以继续向他发问。
+
+### 6.5.3 LangGraph 的优势与局限性分析
+
+任何技术框架都有其特定的适用场景和设计权衡。在本节中,我们将客观地分析 LangGraph 的核心优势及其在实际应用中可能面临的局限性。
+
+(1)优势
+
+如我们的智能搜索助手案例所示,LangGraph 将一个完整的实时问答流程,显式地定义为一个由状态、节点和边构成的“流程图”。这种设计的最大优势是<strong>高度的可控性与可预测性</strong>。开发者可以精确地规划智能体的每一步行为,这对于构建需要高可靠性和可审计性的生产级应用至关重要。
+
+其最强大的特性在于对<strong>循环(Cycles)的原生支持</strong>。通过条件边,我们可以轻松构建“反思-修正”循环,例如在我们的案例中,如果搜索失败,可以设计一个回退到备用方案的路径。这是构建能够自我优化和具备容错能力的智能体的关键。
+
+此外,由于每个节点都是一个独立的 Python 函数,这带来了<strong>高度的模块化</strong>。同时,在流程中插入一个等待人类审核的节点也变得非常直接,为实现可靠的“人机协作”(Human-in-the-loop)提供了坚实的基础。
+
+(2)局限性
+
+与基于对话的框架相比,LangGraph 需要开发者编写更多的<strong>前期代码(Boilerplate)</strong>。定义状态、节点、边等一系列操作,使得对于简单任务而言,开发过程显得更为繁琐。开发者需要更多地思考“如何控制流程(how)”,而不仅仅是“做什么(what)”。
+
+由于工作流是预先定义的,LangGraph 的行为虽然可控,但也缺少了对话式智能体那种动态的、<strong>“涌现”式的交互</strong>。它的强项在于执行一个确定的、可靠的流程,而非模拟开放式的、不可预测的社会性协作。
+
+调试过程同样存在挑战。虽然流程比对话历史更清晰,但问题可能出在多个环节:某个节点内部的逻辑错误、在节点间传递的状态数据发生异变,或是边跳转的条件判断失误。这要求开发者对整个图的运行机制有全局性的理解。
+
+## 6.6 本章小结
+
+本章我们感受了目前最前沿的一些智能体框架,通过案例的形式进行实操体验。
+
+我们看到,每一个框架都有自己实现智能体构建的思路:
+
+- <strong>AutoGen</strong> 将复杂的协作抽象为一场由多角色参与的、可自动进行的“群聊”,其核心在于“以对话驱动协作”。
+- <strong>AgentScope</strong> 则着眼于工业级应用的健壮性与可扩展性,为构建高并发、分布式的多智能体系统提供了坚实的工程基础。
+- <strong>CAMEL</strong> 以其轻量级的“角色扮演”和“引导性提示”范式,展示了如何用最少的代码激发两个专家智能体之间深度、自主的协作。
+- <strong>LangGraph</strong> 则回归到更底层的“状态机”模型,通过显式的图结构赋予开发者对工作流的精确控制,尤其是其循环能力,为构建可反思、可修正的智能体铺平了道路。
+
+通过对这些框架的深入分析,我们可以提炼出一个设计的权衡:<strong>“涌现式协作”与“显式控制”之间的选择</strong>。AutoGen 和 CAMEL 更多地依赖于定义智能体的“角色”和“目标”,让复杂的协作行为从简单的对话规则中“涌现”出来,这种方式更贴近人类的交互模式,但有时难以预测和调试。而 LangGraph 要求开发者明确地定义每一个步骤和跳转条件,牺牲了一部分“涌现”的惊喜,换来了高度的可靠性、可控性和可观测性。同时,AgentScope 则揭示了第二个同样重要的维度:<strong>工程化</strong>。无论我们选择哪种协作范式,要将其从实验原型推向生产应用,都必须面对并发、容错、分布式部署等工程挑战。AgentScope 正是为解决这些问题而生,它代表了从“能运行”到“能稳定服务”的关键跨越。
+
+总而言之,智能体并非只有一种构建方式。深入理解本章探讨的框架设计哲学,能让我们不仅仅成为更优秀的“工具使用者”,更能理解框架设计中的各种优劣与权衡。
+
+在下一章中,我们将进入本教程的核心内容,从零开始,亲手构建一个属于我们自己的智能体框架,将所有理论与实践融会贯通。
+
+
+
+
+
+
+
+
+
+## 参考文献
+
+[1] Wu Q, Bansal G, Zhang J, et al. Autogen: Enabling next-gen LLM applications via multi-agent conversations[C]//First Conference on Language Modeling. 2024.
+
+[2] Gao D, Li Z, Pan X, et al. Agentscope: A flexible yet robust multi-agent platform[J]. arXiv preprint arXiv:2402.14034, 2024.
+
+[3] Li G, Hammoud H, Itani H, et al. Camel: Communicative agents for" mind" exploration of large language model society[J]. Advances in Neural Information Processing Systems, 2023, 36: 51991-52008.
+
+[4] LangChain. LangGraph [EB/OL]. (2024). https://github.com/langchain-ai/langgraph.
+

BIN
docs/images/6-figures/01.png


BIN
docs/images/6-figures/02.png


BIN
docs/images/6-figures/03.png


BIN
docs/images/6-figures/04.png


BIN
docs/images/star-history-2025913.png


BIN
docs/images/star-history-2025916.png


+ 16 - 3
fix_bold_format.py

@@ -15,13 +15,26 @@ def fix_bold_format_in_file(file_path):
         with open(file_path, 'r', encoding='utf-8') as f:
             content = f.read()
         
+        # 先找出所有代码块的位置
+        code_blocks = []
+        code_pattern = r'```[\s\S]*?```'
+        for match in re.finditer(code_pattern, content):
+            code_blocks.append((match.start(), match.end()))
+        
         # 使用正则表达式匹配 **文本** 并替换为 <strong>文本</strong>
-        # 确保不匹配已经是HTML标签的情况
+        # 确保不匹配已经是HTML标签的情况和代码块内的情况
         pattern = r'\*\*([^*]+?)\*\*'
-        replacement = r'<strong>\1</strong>'
+        
+        def replacement_func(match):
+            # 检查匹配位置是否在代码块内
+            match_start = match.start()
+            for block_start, block_end in code_blocks:
+                if block_start <= match_start < block_end:
+                    return match.group(0)  # 在代码块内,不替换
+            return f'<strong>{match.group(1)}</strong>'  # 不在代码块内,进行替换
         
         # 执行替换
-        new_content = re.sub(pattern, replacement, content)
+        new_content = re.sub(pattern, replacement_func, content)
         
         # 如果内容有变化,写回文件
         if new_content != content: