""" Step 01 练习题答案 ⚠️ 先自己思考,再看答案! ⚠️ 答案不是唯一的,这里只是其中一种实现 """ from step_01_tools.concept import BaseTool, ToolResult # ═══════════════════════════════════════════════════════════════════════════════ # 练习 1 答案:TextProcessorTool # ═══════════════════════════════════════════════════════════════════════════════ class TextProcessorTool(BaseTool): """文本处理工具""" @property def name(self) -> str: return "text_processor" @property def description(self) -> str: return "文本处理工具,统计文本的各种特征" def execute(self, **kwargs) -> ToolResult: """处理文本请求""" text = kwargs.get("text", "") operation = kwargs.get("operation", "word_count") if not text: return ToolResult(success=False, error="文本不能为空") if operation == "word_count": result = self.word_count(text) elif operation == "character_count": result = self.character_count(text) elif operation == "sentence_count": result = self.sentence_count(text) else: return ToolResult(success=False, error=f"不支持的操作: {operation}") return ToolResult(success=True, result=result) def word_count(self, text: str) -> int: """统计单词数量""" # 按空格分割,过滤空字符串 words = [w for w in text.split() if w.strip()] return len(words) def character_count(self, text: str) -> int: """统计字符数量(不包括空格)""" # 去除所有空白字符后统计 return len(text.replace(" ", "").replace("\n", "").replace("\t", "")) def sentence_count(self, text: str) -> int: """统计句子数量""" # 按常见句子结束符分割 import re sentences = re.split(r'[.!?]+', text) # 过滤空字符串 sentences = [s for s in sentences if s.strip()] return len(sentences) # ═══════════════════════════════════════════════════════════════════════════════ # 练习 2 答案:EmailTool # ═══════════════════════════════════════════════════════════════════════════════ class EmailTool(BaseTool): """邮件处理工具""" @property def name(self) -> str: return "email" @property def description(self) -> str: return """ 邮件处理工具,用于发送和搜索邮件。 支持的操作: send_email: 发送邮件 - to: 收件人邮箱 - subject: 邮件主题 - body: 邮件正文 返回: {"success": true, "message_id": "xxx"} search_emails: 搜索邮件 - keyword: 搜索关键词 - limit: 返回数量(默认10) 返回: [{"from": "...", "subject": "...", "date": "..."}, ...] get_unread_count: 获取未读邮件数量 无需参数 返回: {"count": 5} """ def execute(self, **kwargs) -> ToolResult: """执行邮件操作""" operation = kwargs.get("operation", "get_unread_count") if operation == "send_email": return self.send_email( to=kwargs.get("to", ""), subject=kwargs.get("subject", ""), body=kwargs.get("body", "") ) elif operation == "search_emails": return self.search_emails( keyword=kwargs.get("keyword", ""), limit=kwargs.get("limit", 10) ) elif operation == "get_unread_count": return self.get_unread_count() else: return ToolResult(success=False, error=f"不支持的操作: {operation}") def send_email(self, to: str, subject: str, body: str) -> ToolResult: """发送邮件""" if not to: return ToolResult(success=False, error="收件人不能为空") if not subject: return ToolResult(success=False, error="主题不能为空") # 实际场景:调用邮件发送 API # 这里用模拟数据 message_id = f"msg_{hash(to + subject) % 100000}" return ToolResult( success=True, result={ "success": True, "message_id": message_id, "to": to, "subject": subject } ) def search_emails(self, keyword: str, limit: int) -> ToolResult: """搜索邮件""" if not keyword: return ToolResult(success=False, error="搜索关键词不能为空") # 模拟搜索结果 mock_results = [ { "from": "boss@company.com", "subject": f"关于项目的{keyword}", "date": "2024-01-15", "snippet": "..." }, { "from": "colleague@company.com", "subject": f"回复: {keyword}的讨论", "date": "2024-01-14", "snippet": "..." }, ] return ToolResult( success=True, result=mock_results[:limit] ) def get_unread_count(self) -> ToolResult: """获取未读邮件数量""" # 实际场景:调用邮件 API 获取未读数 return ToolResult(success=True, result={"count": 5}) # ═══════════════════════════════════════════════════════════════════════════════ # 练习 3 答案:给 ToolRegistry 添加 search_tools # ═══════════════════════════════════════════════════════════════════════════════ from step_01_tools.concept import ToolRegistry, CalculatorTool, SearchTool def add_search_to_registry(): """ 演示如何给 ToolRegistry 添加 search_tools 方法 """ # 方法1:在原类上添加(直接修改原类) def search_tools_original(self, keyword: str) -> list[dict]: """根据关键词搜索工具""" keyword_lower = keyword.lower() results = [] for tool in self._tools.values(): # 检查名称或描述中是否包含关键词 name_match = keyword_lower in tool.name.lower() desc_match = keyword_lower in tool.description.lower() if name_match or desc_match: results.append(tool.to_dict()) return results # 给 ToolRegistry 添加方法 ToolRegistry.search_tools = search_tools_original # 测试 registry = ToolRegistry() registry.register(CalculatorTool()) registry.register(SearchTool()) registry.register(TextProcessorTool()) print("搜索 'text':") for t in registry.search_tools("text"): print(f" - {t['name']}") print("搜索 'calculate':") for t in registry.search_tools("calculate"): print(f" - {t['name']}") print("搜索 'web':") for t in registry.search_tools("web"): print(f" - {t['name']}") # ═══════════════════════════════════════════════════════════════════════════════ # 测试运行 # ═══════════════════════════════════════════════════════════════════════════════ def test_answers(): """测试答案""" print("\n" + "=" * 60) print("测试练习答案") print("=" * 60) # 测试练习 1 print("\n📝 练习 1: TextProcessorTool") tool = TextProcessorTool() test_text = "Hello, world! This is a test. How are you?" print(f"测试文本: {test_text}") print(f"单词数量: {tool.word_count(test_text)}") # 应该是 9 print(f"字符数量: {tool.character_count(test_text)}") # 应该是 38 print(f"句子数量: {tool.sentence_count(test_text)}") # 应该是 3 # 测试练习 2 print("\n📝 练习 2: EmailTool") email_tool = EmailTool() print("\n 发送邮件:") result = email_tool.send_email("test@example.com", "测试", "这是一封测试邮件") print(f" 结果: {result.result}") print("\n 搜索邮件:") result = email_tool.search_emails("项目", limit=5) print(f" 结果: {result.result}") print("\n 未读邮件数:") result = email_tool.get_unread_count() print(f" 结果: {result.result}") # 测试练习 3 print("\n📝 练习 3: search_tools") add_search_to_registry() if __name__ == "__main__": test_answers()